알고리즘/그래프

[백준알고리즘] 그래프(bfs) - 13913번 숨바꼭질4 문제

Fenderblue 2023. 4. 23. 21:49

https://www.acmicpc.net/problem/13913

 

13913번: 숨바꼭질 4

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일

www.acmicpc.net

 

전에 풀어봤던 숨바꼭질 문제와 거의 유사하지만 다른점이 하나 있다면

이번 문제에서는 최단 경로로 거쳐온 각각의 노드들을 표시해야한다는 점이다.

강의에서는 역추적을 하라고 했던것같은데..방법이 잘 안떠올라 다시 강의를 봤다

아 각각의 모든 수들이 어디서 건너왔는지를 기록하는 배열을 만들면 되는구나(from[])

원하는 값만 담은 리스트를 만들어야 한다는 사고에 갇혀있었어서 막혔던듯

한 노드의 이전 노드 정보를 다 기록해놓으면 하나하나씩 역추적이 가능하니까!!

5에서 17까지 5-10-9-18-17 4번만에 도달했으니

17의 이전정보는 18, 18의 이전 정보는 9, 9의 이전정보는 10, 10은 5

이렇게 찾으면 되는데 이대로 출력하면 순서가 반대로 되므로

다시 반대로 출력해주기 위해 스택을 써주는것도 방법이다

 

강의 코드의 이 부분에서도 배우고 갔다. i가 변경되는 부분을 저렇게 해줄수도 있다는것..나중에도 써먹어야쥐

for (int i = end; i != start; i = from[i]) {

 

 

풀이코드

package baekjoonWeek4;

import java.io.*;
import java.util.*;

public class HideAndSeek4 {  //백준 13913번 숨바꼭질 문제
    static ArrayList<ArrayList<Integer>> al;
    static Queue<Integer> queue = new LinkedList<>();
    static ArrayList<Integer> path = new ArrayList<>();
    static int[] visited;
    static int[] from;
    static Stack<Integer> stack = new Stack<>();

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int start = Integer.parseInt(st.nextToken());   //시작할 위치
        int end = Integer.parseInt(st.nextToken());   //도착할 위치
        int max = end;
        if (start > end) {
            max = start;
        }
        max = max * 2 + 1;
        visited = new int[max];
        from = new int[max];
        al = new ArrayList<>(max);
        for (int i = 0; i < max; i++) {
            al.add(new ArrayList<>());
        }

        for (int i = 0; i < max; i++) {
            if (i - 1 >= 0 && i - 1 < max) {
                al.get(i).add(i - 1);
            }
            if (i + 1 >= 0 && i + 1 < max) {
                al.get(i).add(i + 1);
            }
            if (i * 2 >= 0 && i * 2 < max) {
                al.get(i).add(i * 2);
            }
        }

        bw.write(Integer.toString(bfs(start, end)));
        bw.newLine();

        for (int i = end; i != start; i = from[i]) {
            stack.push(i);
        }
        stack.push(start);

        while (!stack.isEmpty()) {
            bw.write(stack.pop() + " ");
        }

        bw.flush();
        bw.close();
    }

    static int bfs(int s, int e) {     //시작점, 도착점
        int now = s;    //현위치
        queue.add(now);
        while (now != e) {  //e에 도달할떄까지
            now = queue.remove();
            for (int i : al.get(now)) {
                if (visited[i] == 0) {  //범위가 0~end 내의 범위이면서 방문 안했을떄
                    queue.add(i);
                    from[i] = now;  //어디에서 왔는지 이전 정보 저장
                    visited[i] = visited[now] + 1;  //이부분이 중요!
                }
            }

        }
        return visited[now];
    }

}