본문 바로가기
문제 풀이/백준

[JAVA 03] 1697. 숨바꼭질

by hyeminigo 2024. 8. 29.

1697. 숨바꼭질 (S1)

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
2 초 128 MB 259328 76710 48775 26.011%

 

 

문제

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.

수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.

입력

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

출력

수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.


summary

수빈이가 동생을 찾을 수 있는 가장 빠른 시간 구하기 

 

- 이동 방법1. 걷기는 X 에서 X-1 또는 X+1 로 이동

- 이동 방법2. 순간이동은 1초 후에 2*X 위치로 이동

- 수빈이는 처음 주어지는 범위 이외에 위치에도 이동이 가능

 

strategy

메모이제이션과  BFS 사용

 

- 수빈이가 몇 초 후에 해당 위치에 도착하는지 기록 (location[])

- 각 위치는 처음 한번만 방문 (location[])

- 수빈이의 이동 위치가 동생위치보다 먼 경우에는 X-1 만 사용 (if 조건)

- 수빈이 위치가 음수일 때는 더 좋은 경우의 수가 될 수 없으므로 고려하지 않음 (if 조건)

 

note

N(0 ≤ N ≤ 100,000), K(0 ≤ K ≤ 100,000)

 

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

public class Main {

    static int N, K;
    static int[] location;
    
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        /* input */
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());

        
        location = N > K ? new int[(N+1) * 2] : new int[(K+1) * 2];

        /* logic */
        BFS();

        /* output */
        System.out.println(location[K] - 1);
    }

    public static void BFS() {
        Queue<Integer> queue = new ArrayDeque<>();
        
        location[N] = 1; // 시작위치
        queue.add(N);
        
        while(!queue.isEmpty()){
            int current = queue.poll();

            int back = current - 1;
            int front = current + 1;
            int teleport = current * 2;

            if(current > 0 && location[back] == 0) { // 처음 방문, 양의 위치
                location[back] = location[current] + 1;
                queue.add(back); 
            }
            if(current < K && location[front] == 0) { // 처음 방문, K위치보다 크지 않음
                location[front] = location[current] + 1;
                queue.add(front); 
            }
            if(current < K && location[teleport] == 0) { // 처음 방문, K위치보다 크지 않음
                location[teleport] = location[current] + 1;
                queue.add(teleport); 
            }

            if(location[K] != 0) break;
        } 
    }
}

 

문제 결과 메모리 시간 언어코드 길이
1697 맞았습니다!! 17168 128  Java 11 / 수정 1646

 

MEMO

 -    이동 경우의 수를 배열로 관리하면 코드가 더 간결해질거같다. (move[] = new int[1, -1, 2])

            int mx = queue.poll();

            for(int m : move) {
                if(m == 2) mx *= 2;
                else mx += m;
            }

            if(mx < 0 || mx > 100000) continue;
            if(arr[mx] != 0) continue;

            location[mx] = location[current] + 1;
            queue.add(mx);

 

- 인덱스 범위 관리하는게 항상 어렵다. 언제쯤 안헷갈릴까 (이번에도 2번이나 런타임에러 뜸) 

// N 이 K보다 큰 경우 고려를 못함
location = new int[(N+1) * 2];

 

'문제 풀이 > 백준' 카테고리의 다른 글

[JAVA06] 1764. 듣보잡  (0) 2024.09.02
[JAVA05] 1620. 나는야 포켓몬 마스터 이다솜  (2) 2024.08.31
[JAVA04] 2529. 부등호  (0) 2024.08.30
[JAVA 02] 2579. 계단 오르기  (0) 2024.08.27
[JAVA 01] 2178. 미로찾기  (0) 2024.08.27