[java]숨바꼭질 4 - 백준13913

문제



풀이

문제 해석을 하자면,

  • 1초에 X-1, X+1, 2*X 이동 가능하며 “수빈” 이 “동생” 을 찾는 최소의 시간을 구하는 문제


풀이

  • 단순히 위에서 말한 3가지 연산을 “브루트포스” 개념으로 접근하면 충분히 구할 수 있다.
    • 단, 시간초과가 발생할 것이다.
  • 이를 위해서 “상태공간트리” 를 그려보면 “BFS” 로 최소 거리 구하는것 처럼 최소시간을 구할 수 있다는걸 알 수 있다.
    • 핵심 원리는 “적절한 범위제한” 과 “이미 기록(방문)한건 무시” 하는게 중요하다.
    • BFS 이기 때문에 “이미 기록(방문)한건 무시” 해도 최소시간(거리)를 구할 수 있다.
    • 이 개념을 잘 이해하고 있어야 이 문제의 풀이가 이해될 것이다.



코드

import java.io.*;
import java.util.*;
/**
 * 1초에 X-1, X+1, 2X 이동 가능
 * => 상태공간트리, BFS특성상 적합
 */
static int N, K; // N:수빈, K:동생
static int[][] dist = new int[100010][2]; // 이전 경로도 같이 기록

public static int calNxt(int cur, int num) {
    if(num == 0) return cur-1;
    else if(num == 1) return cur+1;
    else return cur*2;
}

public static void bfs() {
    for(int i=0;i<100010;i++)
        Arrays.fill(dist[i], -1);
    Queue<Integer> qu = new LinkedList<>();
    qu.add(N);
    dist[N][0] = 0; // "초"(거리) init

    while(!qu.isEmpty()) {
        int cur = qu.peek(); qu.remove();
        for(int i = 0; i<3; i++) {
            int nxt = calNxt(cur, i);
            if(nxt<0||nxt>100005) continue; // 범위 제한(넉넉히 100005까지) => 오버플로 방지
            if(dist[nxt][0] != -1) continue; // 이미 기록된 경우가 "초"(거리)가 작으므로 갱신할 필요가 없다.
            dist[nxt][0] = dist[cur][0]+1; // "초"(거리) 저장
            dist[nxt][1] = cur; // 이전경로 기록
            qu.add(nxt);
        }
    }
}

public static void main(String[] args) throws IOException {
    // input
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
    N = Integer.parseInt(stk.nextToken());
    K = Integer.parseInt(stk.nextToken());
    // run
    bfs();
    // output
    StringBuilder sb = new StringBuilder();
    sb.append(dist[K][0]).append('\n');
    Stack<Integer> st = new Stack<>(); // 출력 용도(거꾸로)
    int pre = K; // init
    for(int i = 0 ; i<=dist[K][0]; i++) {
        st.add(pre);
        pre = dist[pre][1]; // pre update
    }
    while(!st.isEmpty()) {
        sb.append(st.peek()).append(' ');
        st.pop();
    }
    System.out.println(sb);
}



느낀점

생략

댓글남기기