Algorithm/CodingTest

[Algorithm/BOJ] 1697 : 숨바꼭질.py

2025. 9. 28.

문제

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 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초 만에 동생을 찾을 수 있다.

 

첫 풀이 (메모리 초과)

처음에는 큐에 [위치, 시간]을 저장하면서 BFS를 구현하였다. 로컬에서 실행했을 때 알맞은 값이 나왔지만 채점해보니 메모리 초과가 발생하였다.

from collections import deque


def solution(ap, bp):
    queue = deque([[ap, 0]])
    time = 0

    def move(p, t):
        if p - 1 >= 0:
            queue.append([p - 1, t + 1])
        queue.append([p + 1, t + 1])
        queue.append([p * 2, t + 1])
        return

    while queue:
        [p, t] = queue.popleft()

        if p == bp:
            return t

        if t == time:
            move(p, t)

        elif t > time:
            queue.appendleft([p, t])
            time += 1

    return move(ap, 0)


ap, bp = map(int, input().split())
print(solution(ap, bp))

먼저 방문 체크가 없어서 같은 위치를 여러 번 큐에 넣은 것이 잘못되었다. 또한 시간 비교를 위해 (위치, 시간)을 꺼냈다가 다시 집어 넣었는데 BFS이므로 큐가 레벨 순서를 보장한다는 점을 놓쳐 불팔요하게 appendleft를 하였다. 마지막으로 범위에 제한을 두지 않아 p*2 연산으로 인해 큐에 끝없이 큰 값이 들어가면서 메모리를 과도하게 사용하였다.

 

개선된 풀이

  • 방문 여부 체크: 이미 방문한 위치는 다시 큐에 넣지 않는다.
  • 시간은 큐에 함께 저장: appendleft 제거
  • 범위 제한 추가: 0 ≤ p ≤ 100000 범위 내에서 탐색
 
from collections import deque

def solution(ap, bp):
    MAX = 100000
    visited = [False] * (MAX + 1)

    queue = deque([(ap, 0)])
    visited[ap] = True

    while queue:
        p, t = queue.popleft()

        if p == bp:
            return t

        for np in (p - 1, p + 1, p * 2):
            if 0 <= np <= MAX and not visited[np]:
                visited[np] = True
                queue.append((np, t + 1))


ap, bp = map(int, input().split())
print(solution(ap, bp))