문제 출처 : [BOJ 1697] 숨바꼭질, https://www.acmicpc.net/problem/1697
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
예제 입력
5 17
예제 출력
4
수빈이가 5-10-9-18-17 순으로 가면 4초만에 동생을 찾을 수 있다.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class HideAndSick {
static int K;
// 이미 가 본 거리인지 검사하고, 각 단계를 저장해 줄 배열
static int[] visited;
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
K = scan.nextInt();
visited = new int[100001];
// 수빈이의 위치를 기준으로 bfs
search(N);
System.out.println(visited[K] - 1);
scan.close();
}
static void search(int N){
Queue<Integer> queue = new LinkedList<>();
// 탐색 도중, 동생에게 도착했는지 알려 줄 변수
boolean flag = false;
queue.offer(N);
visited[N] = 1;
while(!queue.isEmpty()){
int poll = queue.poll();
// bfs시 연걸 노드의 기준은 수빈이가 현재 위치에서 움직일 수 있는 범위다.
int[] howMove = {poll - 1, poll + 1, poll*2};
for(int i = 0; i < howMove.length; i++){
int move = howMove[i];
// 방문한 적이 없고, 범위를 넘지 않는 경우 이동 가능한 거리를 queue에 추가
if(isBound(move) && (visited[move] == 0)){
queue.offer(move);
visited[move] = visited[poll] + 1;
}
if(move == K){
flag = true;
}
}
// 수빈이가 탐색 도중 동생을 만났다면 루프 탈출
if(flag){
break;
}
}
}
// move가 배열 범위를 넘으면 false, 아니면 true를 반환하는 메서드
static boolean isBound(int move){
if(move >= 0 && move < visited.length){
return true;
}
return false;
}
}
짧은 문제 설명, 짧은 코드, 그렇지 못한 난이도...😂
문제 해결 방법은 굉장히 빨리 생각해냈는데, 히든 케이스 때문에 예외처리하느라 애먹었다.😭
특히 문제에서 대놓고 K와 N의 범위는 같다고 해놨는데, 자꾸 수빈이가 뒤에 있고 동생이 앞에 있는 식으로 문제를 이해해서 시간을 좀 많이 버렸었다.😑😓
빠르고 정확한 문제 이해도 중요하지만, 입출력 범위도 항상 염두에 두고 하자!!👀