Algorithm
백준 1697번: 숨바꼭질
10Biliion
2025. 3. 20. 19:56

너비 우선 탐색(BFS, Breadth-First Search) 알고리즘을 사용하여 주어진 숫자 a에서 b로 가는 최소 횟수를 구하는 문제입니다.
주어진 정수 a와 b에 대해, a에서 시작해 여러 가지 연산을 통해 b에 도달하려면 최소 몇 번의 연산이 필요한지를 구하세요. 가능한 연산은 다음과 같습니다:
- 현재 숫자에서 1을 뺀다.
- 현재 숫자에 1을 더한다.
- 현재 숫자에 2를 곱한다.
코드
import java.io.*;
import java.util.*;
public 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 a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
System.out.println(bfs(a, b));
}
static int bfs(int a, int b) {
if (a == b) return 0;
Queue<Integer> queue = new LinkedList<>();
queue.offer(a);
int[] visited = new int[100001];
while (!queue.isEmpty()) {
int now = queue.poll();
for (int next : new int[] {now - 1, now + 1, now * 2}) {
if (next >= 0 && next <= 100000 && visited[next] == 0) {
queue.offer(next);
visited[next] = visited[now] + 1;
if (next == b) return visited[next];
}
}
}
return -1;
}
}
BFS 함수 (bfs(int a, int b)):
- BFS 탐색을 통해 a에서 b로 가는 최소 연산 횟수를 구합니다.
- visited 배열을 사용하여 각 숫자를 몇 번째 연산에서 방문했는지 기록합니다. 초기값은 모두 0으로 설정되며, 각 숫자는 처음 방문할 때 그때의 연산 횟수를 기록합니다.
- BFS를 수행하면서 각 숫자에서 가능한 세 가지 연산을 진행합니다:
- 현재 숫자에서 1을 뺀다.
- 현재 숫자에 1을 더한다.
- 현재 숫자에 2를 곱한다.
- 연산을 통해 도달한 숫자는 queue에 넣고, 해당 숫자가 b와 같으면 연산 횟수를 반환합니다.
- 만약 BFS 탐색이 끝날 때까지 b에 도달하지 못하면 -1을 반환합니다.
큐와 방문 처리
- 큐(Queue<Integer> queue)를 사용하여 BFS 탐색을 진행합니다. 큐에 숫자를 넣고, 큐에서 숫자를 꺼내어 그 숫자에서 가능한 연산을 진행합니다.
- visited[next] 값은 각 숫자를 처음 방문했을 때 연산 횟수를 기록합니다. 이를 통해 이미 방문한 숫자는 다시 방문하지 않도록 하여 중복 탐색을 방지합니다.
시간 복잡도
- 각 숫자에서 3개의 연산을 수행하고, 각 연산에 대해 next 값이 유효한지 확인합니다. 각 연산은 O(1) 시간에 처리할 수 있습니다.
- 큐에 최대 100,001개의 숫자가 들어갈 수 있으며, 각 숫자에 대해 3개의 연산을 수행하므로 총 연산 횟수는 대체로 O(3 * 100001)입니다.
- 상수인 3을 제외하고, 시간 복잡도는 **O(N)**입니다. 여기서 N은 100,001이므로, O(N) 시간 복잡도가 됩니다.