Programming/백준

[실버 1] 백준 12849 - 본대 산책 (파이썬)

pental 2025. 6. 21. 12:36

https://www.acmicpc.net/problem/12849

풀이

  • 총 8개의 장소(0~7번 정점)로 구성된 캠퍼스가 있고, 하루에 1분씩 이동할 수 있음.
  • 이동 가능한 경로는 문제에서 고정되어 있음 (총 12개 간선)
  • 0번에서 시작해 정확히 D분 뒤 다시 0번에 도착할 수 있는 모든 경로의 수를 구하는 문제.
  • 단, 결과는 10^9 + 7로 나눈 나머지를 출력.
adj = [[] for _ in range(8)]
edge = [ ... ]  # 문제에서 주어진 12개 간선

for a, b in edge:
    adj[a].append(b)
    adj[b].append(a)

먼저 인접 리스트를 정의하고, adj[i]는 i번 정점에서 갈 수 있는 이웃 정점을 리스트로 담고 있다.

양방향 그래프이므로 adj[a].append(b)와 adj[b].append(a)가 모두 필요하다.

dp = [[0] * 8 for _ in range(D + 1)]
dp[0][0] = 1

dp 테이블을 정의하며, dp[i][j]는 i분 후에 j번 정점에 도착하는 경우의 수를 의미한다.

시작점은 0번이므로 dp[0][0] = 1로 초기화 한다.

for i in range(1, D + 1):
    for j in range(8):
        dp[i][j] = 0
        for k in adj[j]:
            dp[i][j] += dp[i - 1][k]
            dp[i][j] %= mod

점화식은 위 코드와 같이 구성한다.

현재 시각 i분일때 정점 j에 도달하는 경우의 수는 j로 들어오는 모든 인접한 정점 k에서 i - 1분에 도착했던 경우의 수의 합이다.

따라서 dp[i][j] = sum(dp[i - 1][k] for k in adj[j])가 된다.

시간복잡도

  • 시간 복잡도는 O(D × 8 × deg)
  • deg = 평균 연결 정점 수 = 약 2~3 → 충분히 빠름 (D ≤ 100)

코드

# 백준 12849 - 본대 산책
# 분류 : 다이나믹 프로그래밍

D = int(input())
mod = int(1e9 + 7)

adj = [[] for _ in range(8)]

edge = [
    (0, 1),
    (0, 2),
    (1, 2),
    (1, 3),
    (2, 3),
    (2, 4),
    (3, 4),
    (3, 5),
    (4, 5),
    (4, 6),
    (5, 7),
    (6, 7)
]

for a, b in edge :
    adj[a].append(b)
    adj[b].append(a)

dp = [[0] * 8 for _ in range(D + 1)]
dp[0][0] = 1

for i in range(1, D + 1) :
    for j in range(8) :
        dp[i][j] = 0
        for k in adj[j] :
            dp[i][j] += dp[i - 1][k]
            dp[i][j] %= mod

print(dp[D][0])