[백준] #13549. 숨바꼭질 3 (파이썬/Python)

2025. 6. 22. 09:33·Coding Practice/Backjoon

 


📖 문제

[백준] #13549. 숨바꼭질 3 (파이썬/Python)

  • 난이도: 골드5
  • 유형: BFS
문제 요약

수빈이는 현재 위치 `N`에 있고, 동생은 `K`에 있다.

수빈이는 다음 3가지 방법으로 이동할 수 있다.

  • `X - 1` (1초 소요)
  • `X + 1` (1초 소요)
  • `2 * X` (0초 소요)

목표는 동생에게 도달하는 데 걸리는 최소 시간(초)을 구하는 것이다.

(숨바꼭질 시리즈)


🔍 문제 접근

💡 문제 분석

처음에 틀린 이유를 찾을 수가 없어서 GPT의 도움을 받았다.

이 문제는 가중치가 0 또는 1인 그래프에서의 최단 거리 문제이다.

  • `X → 2X`는 이동 시간 0 → 가중치 0
  • `X → X±1`은 이동 시간 1 → 가중치 1

이처럼 간선 가중치가 0 또는 1일 경우, 일반 BFS가 아닌 0-1 BFS 기법을 사용해야 한다.

 

🚀 0-1 BFS란?

0-1 BFS는 간선 가중치가 0 또는 1인 그래프에서 최단 경로를 빠르게 구하는 알고리즘이다.

일반적인 BFS와 유사하지만, 다음과 같은 특징이 있다:

  0-1 BFS 다익스트라 (heapq)
간선 가중치 0 또는 1만 허용 양의 정수 아무 값
사용 자료구조 deque 우선순위 큐 (heapq)
시간 복잡도 O(V + E) O((V + E) log V)
처리 속도 더 빠름 비교적 느림

작동방식

  • 가중치가 0이면 `appendleft()`를 사용하여 큐의 앞쪽에 넣는다.
    • → 즉시 처리하여 빠르게 탐색한다.
  • 가중치가 1이면 `append()`를 사용하여 큐의 뒤쪽에 넣는다.
    • → 하나의 시간 단위가 지난 후 처리된다.

이렇게 하면 별도의 우선순위 큐 없이도, 가중치에 따라 탐색 순서가 자동으로 조절된다

 

🧠 풀이 아이디어

BFS 로직은 다음과 같다.

  • 시작점 `N`부터 BFS 탐색을 진행한다.
  • `visited[x]`에는 `x` 위치에 도달하는 데 걸린 최소 시간을 저장한다.
  • 큐를 탐색하며 큐에 있는 값을 `current`에 저장한다.
  • 순간이동 (`current * 2`)는 0초로, 우선적으로 탐색되어야 한다. 따라서 `current * 2`를 먼저 처리하고, `appendleft()`로 처리한다.
    • 범위 내에 있고 방문한 적이 없을 경우 `current * 2` 위치까지 걸린 시간은 `current`와 동일하다.
    • 큐에 추가한다. (`appendleft`)
  • 걷기 (`current + 1`, `current - 1`)는 1초 걸리므로 `append()`로 추가한다.
    • 범위 내에 있고 방문한 적이 없을 경우 `current * 2` 위치까지 걸린 시간은 `current`에 1을 더한 값이다.
    • 큐에 추가한다. (`append`)
  • 탐색 중에 `K`에 도달하면 최소 시간이므로 바로 종료한다.

 


🔍 문제 풀이

♻️ 코드 플로우
  1. 최대 좌표값인 `100000`까지 탐색할 수 있도록 범위 상수를 선언한다.
  2. `visited` 리스트를 `1`로 초기화하여 방문 여부와 시간을 동시에 기록한다.
  3. `deque`를 생성하고 시작 위치를 넣는다.
  4. 다음 규칙에 따라 큐를 순회하며 위치를 탐색한다:
    • `2 * x` (순간이동): `appendleft()`, 시간 변화 없음
    • `x ± 1 `(걷기): `append()`, 시간 +1
  5. 목표 위치 K에 도달하면 종료한다.

🚩 제출한 소스 코드

import sys
from collections import deque
input = sys.stdin.readline

MAX = 100000
N, K = map(int, input().split())
visited = [-1] * (MAX + 1)

queue = deque()
queue.append(N)
visited[N] = 0

while queue:
    current = queue.popleft()

    # 순간이동 (0초) -> 큐 앞쪽에 넣기
    nx = current * 2
    if 0 <= nx <= MAX and visited[nx] == -1:
        visited[nx] = visited[current]
        queue.appendleft(nx)  # 핵심!

    # 걷는 경우 (+1, -1) -> 큐 뒤쪽에 넣기
    for nx in (current - 1, current + 1):
        if 0 <= nx <= MAX and visited[nx] == -1:
            visited[nx] = visited[current] + 1
            queue.append(nx)

print(visited[K])

  • 틀렸던 이유
    • 문제의 핵심은 아래와 같다.
      • 2로 순간이동하는 경우는 시간이 0초.
      • +1, 1로 걷는 경우는 시간이 1초.
    • 이 경우에는 가중치가 0 또는 1인 그래프 → 0-1 BFS 필요하다.
    • 하지만 틀린 풀이에서는 가중치에 다라 처리하지 않았다.
      • 0초 걸리는 이동 (2)는 앞쪽에 appendleft() 해야 하고,
      • 1초 걸리는 이동 (+1, 1)은 뒤쪽에 append() 해야 최단 경로를 제대로 탐색할 수 있다.

🚩 다른 분의 풀이

 

[백준] 13549. 숨바꼭질3 (파이썬)

문제 https://www.acmicpc.net/problem/13549 풀이접근 1697. 숨바꼭질 문제처럼 풀되, 조건에 맞게 조금의 수정을 하면 되겠다 생각. 위 문제에서는 특별히, 순간이동을 하는 경우에는 0초 밖에 걸리지 않는

velog.io

import heapq
INF = int(1e9)

N, K = map(int, input().split())
distance = [INF] * 100001

def dijkstra(start):
    distance[start] = 0
    q = []
    heapq.heappush(q, (0, start))

    while q:
        dist, now = heapq.heappop(q)
        if distance[now] < dist:
            continue
        for n in (now+1, now-1, now*2):
            if n < 0 or n > 100000:
                continue

            cost = dist
            if n != now*2:
                cost = dist + 1

            if cost < distance[n]:
                distance[n] = cost
                q.append((cost, n))

dijkstra(N)
print(distance[K])

💡회고

  • 이 문제가 숨바꼭질2와 다른 점은 “0초 이동”을 처리해야 한다는 것이다. 숨바꼭질2와 비슷하게 풀면 정확할 수 없다.
  • 이 문제를 통해서 0-1 BFS 유형을 알게 되었다. `0-1 BFS`를 구현하기 위해서는 우선순위가 높은 것은 (deque 기준으로) `appendleft`로 우선 탐색할 수 있도록 해주어야 한다는 것을 알게 되었다.
  • `heapq`로도 풀이 가능하다.
저작자표시 비영리 변경금지 (새창열림)

'Coding Practice > Backjoon' 카테고리의 다른 글

[백준] #14226. 이모티콘 (파이썬/Python)  (1) 2025.06.18
[백준] #20546. 🐜 기적의 매매법 🐜 (파이썬/Python)  (5) 2025.06.15
[백준] #1697. 숨바꼭질(파이썬/Python)  (0) 2025.06.15
[백준] #12851. 숨바꼭질 (파이썬/Python)  (0) 2025.06.15
[백준] #1715. 카드 정렬하기  (0) 2025.06.08
'Coding Practice/Backjoon' 카테고리의 다른 글
  • [백준] #14226. 이모티콘 (파이썬/Python)
  • [백준] #20546. 🐜 기적의 매매법 🐜 (파이썬/Python)
  • [백준] #1697. 숨바꼭질(파이썬/Python)
  • [백준] #12851. 숨바꼭질 (파이썬/Python)
밍구링구리
밍구링구리
밍구리의 실험실 이것저것 배우고 기록을 남깁니다
  • 밍구링구리
    Mingguri Labatory
    밍구링구리
  • 전체
    오늘
    어제
    • 분류 전체보기 (81) N
      • Language & Framework (15) N
        • Java (3) N
        • Vue.js (1)
        • Spring Boot (10) N
      • Computer Science (2) N
        • Operating System) (0)
        • Database (0)
        • Network (1) N
        • Data Structure (0)
        • Algorithm (1)
      • Architecture & Design (7)
      • Cloud & Infra (5)
      • Trouble Shooting (0)
        • 에러 해결 (0)
        • 삽질 기록 (0)
      • 회고 (0)
      • Coding Practice (32) N
        • Backjoon (17)
        • LeetCode (6)
        • Programmers (9) N
      • ETC (18)
        • 일상 (1)
        • 후기 (2)
        • 밍구의 실험실 (1)
        • 🤔Study . Question🔍 (14)
      • 부트캠프 (1) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 깃허브
    • 소개
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 태그

    문제
    퀴즈
    백준
    프로그래머스
    LeetCode
    골드4
    git
    스터디
    BFS
    코딩테스트
    객체지향
    OOP
    구현
    SOLID
    알고리즘
  • hELLO· Designed By정상우.v4.10.3
밍구링구리
[백준] #13549. 숨바꼭질 3 (파이썬/Python)
상단으로

티스토리툴바