PS/BFS & DFS

백준 17071번: 숨바꼭질 5 (JAVA)

닻과매 2022. 6. 2. 11:38

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

 

17071번: 숨바꼭질 5

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

www.acmicpc.net

문제

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 500,000)에 있고, 동생은 점 K(0 ≤ K ≤ 500,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다. 동생은 항상 걷기만 한다. 동생은 항상 매 초마다 이동을 하며, 이동은 가속이 붙는다. 동생이 이동하는 거리는 이전에 이동한 거리보다 1을 더한 만큼 이동한다. 즉, 동생의 처음 위치는 K, 1초가 지난 후 위치는 K+1, 2초가 지난 후 위치는 K+1+2, 3초가 지난 후의 위치는 K+1+2+3이다.

수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오. 동생을 찾는 위치는 정수 좌표이어야 하고, 수빈이가 0보다 작은 좌표로, 50만보다 큰 좌표로 이동하는 것은 불가능하다.

입력

첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.

출력

수빈이가 동생을 찾는 가장 빠른 시간을 출력한다. 수빈이가 동생을 찾을 수 없거나, 찾는 위치가 500,000을 넘는 경우에는 -1을 출력한다.

 


 

감도 안 잡혀서 한 줄 힌트를 보고 풀었다.

힌트

'어떤 자리 N에 X번만에 왔다면, X+2, X+4, .. 번째에도 N에 있을 수 있다.;'

 

 

풀이

동생도 움직이기에, 단순히 bfs를 써서 어떤 위치까지 이동하는 최소 시간만 구한다면 모든 경우를 놓칠 수 있다. 모든걸 기록한다는 관점으로 boolean 이차원 배열 [위치][현재시간]을 만들어 (위치, 현재시간)에 대해 수빈이가 있을 수 있따면 true로 하는 풀이를 생각해 볼 수 있으나, 위치 <= 50만, 현재시간 <= (대략 sqrt(50만))이므로 시간 초과는 둘째치고, 일단 메모리 초과가 뜰 것이다.

힌트를 이용한 풀이: 특정 위치 N에 최소로 도달하는 '짝수 소요시간'과 '홀수 소요시간'을 기록한다. 예를 들어, 5에 도달하는데 '최소 짝수 소요시간'은 4, '최소 홀수 소요시간'이 7이라면, 4, 6, 8, 10, ... , 그리고 7, 9, 11, ...인 시간에는 해당 위치에 있을 수 있다. 따라서, 각 소요시간마다 동생의 위치에 대하여 현재 소요시간보다 작으며 현재 소요시간과 홀짝성이 같은 도착 기록이 있다면 해당 위치에서 수빈이는 동생을 만날 수 있다.

 

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[][] dist = new int[2][500001];
        Arrays.fill(dist[0], -1);
        Arrays.fill(dist[1], -1);
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int K = Integer.parseInt(st.nextToken());
        dist[0][N] = 0;
        Queue<int[]> queue = new ArrayDeque<>();
        queue.offer(new int[] {N, 0});

        if (N == K) {
            System.out.println(0);
            return;
        }
        int time = 0;
        while (!queue.isEmpty()) {
            time++;
            K += time;
            if (K > 500000) break;
            int size = queue.size();
            while (size-- > 0) {
                int[] cur = queue.poll();
                int loc = cur[0], len = cur[1];
                if (2*loc <= 500000 && dist[(len+1)%2][2*loc] < 0) {
                    dist[(len+1)%2][2*loc] = len+1;
                    queue.offer(new int[] {2*loc, len+1});
                } 
                if (loc+1 <= 500000 && dist[(len+1)%2][loc+1] < 0) {
                    dist[(len+1)%2][loc+1] = len+1;
                    queue.offer(new int[] {loc+1, len+1});
                }
                if (loc-1 >= 0 && dist[(len+1)%2][loc-1] < 0) {
                    dist[(len+1)%2][loc-1] = len+1;
                    queue.offer(new int[] {loc-1, len+1});
                }
            }
            if (dist[time%2][K] >= 0) {
                System.out.println(time);
                return;
            }
        }
        System.out.println(-1);
    }
}

'PS > BFS & DFS' 카테고리의 다른 글

백준 11967번: 불켜기 (JAVA)  (0) 2022.06.03
백준 9328번: 열쇠 (JAVA)  (0) 2022.06.03
백준 1038번: 감소하는 수 (JAVA)  (0) 2022.05.31
백준 9019번: DSLR (JAVA)  (0) 2022.04.05
백준 1600번: 말이 되고픈 원숭이 (JAVA)  (0) 2022.02.25