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는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
문제 접근
- BFS 알고리즘을 사용한다(다른 방식으로도 가능).
- 현재 위치에서 수빈이가 갈 수 있는 곳을 모두 큐에 집어넣는다.
- 큐에서 꺼내면서 실제로 이동한다.
- 이동한 위치에는 그 위치에 도달하기까지 걸린 시간을 저장한다.
- 이미 저장된 시간이 있는 경우, 즉 이미 방문했던 곳은 가지 않는다(이미 가장 빠른 시간이 아니므로).
문제 풀이
private static int N;
private static int K;
private static int[] location = new int[100001];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String[] temp = br.readLine().trim().split(" ");
N = Integer.parseInt(temp[0]);
K = Integer.parseInt(temp[1]);
/* output */
bw.write(""+bfs(N));
bw.flush();
bw.close();
}
필요한 변수들을 선언하고 input을 받아온다. 실제 동작은 BFS 함수에서 이루어지므로 메인은 간단하다.
public static int bfs(int n) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(n);
location[n] = 0;
while(!q.isEmpty()) {
int x = q.poll();
if(x == K) {
return location[x];
}
if(0 <= x-1 && location[x-1] == 0) { //x-1
q.offer(x-1);
location[x-1] = location[x]+1; // +1sec
}
if(x+1 <= 100000 && location[x+1] == 0) { // x+1
q.offer(x+1);
location[x+1] = location[x]+1;
}
if(2*x <= 100000 && location[2*x] == 0) { // 2*x
q.offer(2*x);
location[2*x] = location[x]+1;
}
}
return -1; // fail
}
시작 위치의 도달 시간은 0이므로, location[n]에는 0을 넣고 시작한다. x는 현재 위치이며 큐에서 꺼낸 위치로 이동한다.
현재 위치가 목표 위치와 같아지면 그때의 시간을 반환한다.
그 아래의 if문들에서는 갈 수 있는 위치인지 판단하는데, 일단 좌표가 허용범위여야 하며 방문한 적이 없어야 한다. 셋 중 하나로 가는 것이 아니라 세 곳 다 가능성을 두고 탐색해야 한다. 갈 수 있는 곳의 좌표를 큐에 넣은 후, 그곳의 도달 시간을 저장한다. 현재 위치에서 1초면 갈 수 있기 때문에 현재 위치의 도달 시간 + 1을 해준다.
혹시나 아무 곳에도 갈 수 없으면(큐가 비는 경우) 불가능의 의미로 -1을 리턴해주었는데, 불가능한 테스트케이스는 나오지 않으므로 별 의미는 없다.
전체 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.Queue;
public class BFS1697 {
private static int N;
private static int K;
private static int[] location = new int[100001];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String[] temp = br.readLine().trim().split(" ");
N = Integer.parseInt(temp[0]);
K = Integer.parseInt(temp[1]);
/* output */
bw.write(""+bfs(N));
bw.flush();
bw.close();
}
public static int bfs(int n) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(n);
location[n] = 0;
while(!q.isEmpty()) {
int x = q.poll();
if(x == K) {
return location[x];
}
if(0 <= x-1 && location[x-1] == 0) { //x-1
q.offer(x-1);
location[x-1] = location[x]+1; // +1sec
}
if(x+1 <= 100000 && location[x+1] == 0) { // x+1
q.offer(x+1);
location[x+1] = location[x]+1;
}
if(2*x <= 100000 && location[2*x] == 0) { // 2*x
q.offer(2*x);
location[2*x] = location[x]+1;
}
}
return -1; // fail
}
}
결과 및 평가
딱히 막 결과가 좋진 않다. 더 효율적인 방식이 있을텐데... 아무래도 빠른 시간을 찾는거니까 조건을 따져서 순간이동을 제일 많이 하고 도착할 수 있게 해주면 되지 않을까? BFS 공부 목적으로 푼거라 나중에 생각나면 시도해야겠다.
'문제풀이' 카테고리의 다른 글
[백준 1107] 리모컨 - JAVA (0) | 2023.01.12 |
---|---|
[백준 14499] 주사위 굴리기 - JAVA (0) | 2022.02.09 |
[백준 10815] 숫자 카드 - JAVA (0) | 2022.01.07 |
[백준 1946] 신입 사원 - JAVA (0) | 2022.01.06 |
Comment