백준 풀이
백준 / python / 2098. 외판원 순회
땡구리
2023. 2. 8. 16:08
https://www.acmicpc.net/problem/2098
문제 요약
2~16(N)개의 도시가 주어질 때, 최소한의 비용으로 모든 도시를 순회할 때 발생하는 비용을 구하라.
풀이 요약
- "순회" 를 하기 때문에 어느 지점에서 시작해도 상관이 없다. A 가 시작 도시라고 해보자.
- A~E 의 도시를 방문하였고 F ~ Z 의 도시를 앞으로 방문해야하며 현재 도시는 E 라면, A~D 의 방문 순서가 어떤 순서였던지간에 상관없이, 항상 같은 비용(E에서 F~Z 를 방문하고 마지막에A 로 방문하는 최소 비용)을 추가해야할 것이다. 이 비용을 저장해서 dp 로 푸는 것이 핵심이다.
- 방문했는지 여부를 N 개의 정수로 나타낼 수도 있겠지만 비트마스킹을 사용하여 한 개의 정수로 나타내면 메모리를 절약할 수 있다.
- 그럼 dp[now][10011] 은 1, 2, 5 번 도시를 방문하였고 현재 now 번 도시에서 1, 2, 5 번 도시를 제외한 도시들을 거쳐 A 로 돌아가는 비용이다.
주의사항
- 리스트가 딕셔너리보다 200ms 정도 빠르다.
- min 을 안쓰면 300ms 빨라진다.
from sys import stdin, maxsize
input = stdin.readline
N = int(input())
costs = []
dp = [[0] * (1 << N) for _ in range(N)]
INF = maxsize
for _ in range(N):
costs.append(list(map(int, input().split())))
def solve(now, index):
if index == (1 << N) - 1:
return costs[now][0] if costs[now][0] else INF
if dp[now][index]:
return dp[now][index]
dp[now][index] = INF
for i, value in enumerate(costs[now]):
if value == 0:
continue
if index & (1 << i):
continue
temp = solve(i, index | (1 << i)) + value
if dp[now][index] > temp:
dp[now][index] = temp
return dp[now][index]
print(solve(0, 1))