백준 13549번: 숨바꼭질 3
📌 문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
📝 문제 분석
✨문제 상황
수빈이는 동생과 숨바꼭질을 하고 있습니다. 두 사람은 정수형 1차원 좌표 위에 있으며 수빈이는 위치 N에 있고 동생은 위치 K에 있습니다.
수빈이는 매번 아래 세 가지 방법으로 이동할 수 있습니다.
이동 방식 | 수식 표현 | 시간(비용) |
한 칸 뒤로 이동 | $X \rightarrow X - 1$ | 1초 |
한 칸 앞으로 이동 | $X \rightarrow X + 1$ | 1초 |
순간이동 | $X \rightarrow X \times 2$ | 0초 |
🎯 목표: 수빈이가 동생을 가장 빠르게 찾기 위한 최소 시간을 구하는 것입니다.
⚾ 일반적인 BFS로 풀 수 있을까?
BFS는 그래프나 좌표계에서 최단 거리(최소 비용)를 찾는 데 자주 사용됩니다. 특히 모든 이동의 비용이 동일할 때 BFS는 가장 먼저 도달한 경로가 항상 최단 경로가 됩니다.
✅ 일반적인 BFS의 특징
- 모든 간선(이동)의 비용이 동일
- 예: 미로 탐색 → 상하좌우 1칸 이동 모두 1초
- 처음 방문한 경로가 곧 최단 경로
- 가까운 지점부터 순차적으로 탐색하기 때문
⚠ 하지만 이 문제는 일반적인 BFS로 풀 수 없습니다.
이 문제는 이동에 걸리는 시간이 서로 다릅니다.
- 앞으로 한 칸 이동과 뒤로 한 칸 이동의 경우 1초
- 순간이동의 경우 0초
이처럼 이동 비용이 서로 다른 경우 단순 BFS는 더 빠른 경로를 나중에 처리할 수 있으므로 최단 시간을 보장하지 않습니다.
📉 일반적인 BFS가 실패하는 예시
현재 수빈이의 위치가 5일 때 가능한 이동은 다음과 같습니다.
이동 | 도착 위치 | 소요 시간 |
$5 - 1$ | 4 | 1초 |
$5 + 1$ | 6 | 1초 |
$5 \times 2$ | 10 | 0초 |
일반적인 BFS는 이동 순서를 순차적으로 큐에 넣기 때문에 다음과 같이 처리됩니다.
queue = [4, 6, 10]
- 순간이동으로 즉시 도달 가능한 위치인 10이 오히려 늦게 처리됩니다. 이로 인해 빠른 경로가 후순위로 밀리게 되어 최단 시간을 보장하지 않습니다.
✅ 0-1 BFS를 사용하자
0-1 BFS는 간선 가중치가 0 또는 1인 그래프에서 최단 경로를 구하는 알고리즘입니다. 핵심은 덱(Deque)을 이용해 이동 비용이 적은 경로를 먼저 탐색할 수 있게 만드는 것입니다.
- 시간 비용이 0인 이동은 덱의 앞쪽에 추가합니다.
- 시간 비용이 1인 이동은 덱의 뒤쪽에 추가합니다.
🔁 예제로 다시 보기
이동 | 도착 위치 | 시간 | 덱에 넣는 위치 |
$X - 1$ | 4 | 1초 | 뒤쪽 |
$X + 1$ | 6 | 1초 | 뒤쪽 |
$X /times 2$ | 10 | 0초 | 앞쪽 |
deque = [10, 4, 6]
- 이렇게 하면 순간이동으로 갈 수 있는 10이 먼저 탐색되며 보다 빠른 경로를 우선적으로 처리할 수 있습니다.
💡 해결 방법
🎯 목표 재확인
- 수빈이의 위치 N에서 출발하여 동생의 위치 K까지 가장 빠른 시간에 도달해야 합니다.
- 순간이동은 시간 비용이 0초, 한 칸 이동은 1초이기 때문에 이동 방식에 따라 우선 탐색 순서가 달라야 합니다.
- 따라서 0-1 BFS 알고리즘을 적용해야 합니다.
📌 핵심 구현 전략
- 덱(Deque)을 사용하여 앞뒤 삽입이 가능하도록 합니다.
- time[] 배열을 만들어 각 위치까지 도달하는 최소 시간을 기록합니다.
- 매 순간 X - 1, X + 1, X * 2 세 가지 이동을 시도합니다.
- 순간이동은 0초 → appendleft()
- 한 칸 이동은 1초 → append()
- 목표 위치 K에 처음 도달했을 때의 시간이 정답입니다.
🧮 0-1 BFS 알고리즘 흐름
- deque를 생성하고 시작 위치 N을 넣습니다.
- time 배열을 -1로 초기화하고 time[N] = 0으로 설정합니다.
- 덱이 빌 때까지 다음을 반복합니다.
- 현재 위치를 꺼냅니다.
- 다음 위치 후보 (X - 1, X + 1, X * 2)를 계산합니다.
- 아직 방문하지 않은 위치만 처리합니다.
- 순간이동: 위치 2 * X & 시간 증가 없음 → 덱 앞에 추가
- 한 칸 이동: 위치 X + 1, X - 1 & 시간 1초 증가 → 덱 뒤에 추가
- current == K가 되는 순간 time[K]를 반환합니다.
👩💻 나의 답안
from collections import deque
import sys
input = sys.stdin.readline
def bfs(n, k):
if n >= k:
return n - k
max_pos = 2 * k + 1
time = [-1] * max_pos
queue = deque([n])
time[n] = 0
while queue:
current = queue.popleft()
if current == k:
return time[k]
for next in (current - 1, current + 1, current * 2):
if 0 <= next < len(time) and time[next] == -1:
if next == current * 2:
time[next] = time[current]
queue.appendleft(next)
else:
time[next] = time[current] + 1
queue.append(next)
n, k = map(int, input().split())
time = bfs(n, k)
print(time)
Algorithm/백준/Gold/13549. 숨바꼭질 3 at main · kuun1000/Algorithm
This is a auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - kuun1000/Algorithm
github.com
'코딩테스트 대비' 카테고리의 다른 글
[파이썬(Python)] 백준 2250번 트리의 높이와 너비 (0) | 2025.04.03 |
---|---|
[파이썬(Python)] 백준 1261번 알고스팟 (0) | 2025.04.01 |
[파이썬(Python)] 백준 14226번 이모티콘 (0) | 2025.03.26 |
[파이썬(Python)] 백준 13913번 숨바꼭질 4 (0) | 2025.03.25 |
[파이썬(Python)] 백준 2146번 다리 만들기 (0) | 2025.03.24 |