알고리즘/백준
13549 - 숨바꼭질 3[G5]
블랑v
2024. 10. 16. 23:28
문제
https://www.acmicpc.net/problem/13549
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
풀이
풀이의 핵심은 PQ 사용을 통한 '가장 짧은 시간'을 항시 탐색하는 것.
3가지의 조건 분기를 PQ에 던지기만 한다면 heap을 통해 최단 거리를 항상 판정할 수 있다.
또한 중복 처리 방지를 위해 visited를 사용하고 큐에서 빠졌을 때 방문 처리를 하는 것. (이전에 처리해서 에러가 났었다.)
코드
import java.util.*;
import java.io.*;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken()); //수빈이 위치
int k = Integer.parseInt(st.nextToken()); //목표
//메모리 초과 해결 위함 : 중복된 좌표를 동일 반복 가능하기에 체크 표시 필요
boolean[] visited = new boolean[100000 + 1];
PriorityQueue<Pos> pq = new PriorityQueue<>();
pq.add(new Pos(n, 0)); //현재 수빈이 위치 기준
while (!pq.isEmpty()) {
Pos now = pq.poll();
if(visited[now.x]) continue;
visited[now.x] = true;
if(now.x == k) { //목표 달성
System.out.println(now.time);
return;
}
if(now.x > 0 && !visited[now.x - 1]) {
pq.add(new Pos(now.x - 1, now.time + 1));
}
if(now.x < 100000 && !visited[now.x + 1]) {
pq.add(new Pos(now.x + 1, now.time + 1));
}
if(now.x * 2 <= 100000 && now.x > 0 && !visited[now.x * 2]) {
pq.add(new Pos(now.x * 2, now.time));
}
}
}
}
class Pos implements Comparable<Pos> {
int x; //위치
int time; //걸린 시간
public Pos(int x, int time) {
this.x = x;
this.time = time;
}
@Override
public int compareTo(Pos p) {
return Integer.compare(this.time, p.time); //시간 적은 순서대로
}
}