문제 링크
https://www.acmicpc.net/problem/2098
2098번: 외판원 순회
첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 16) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j
www.acmicpc.net
풀이 - 다른 블로그 참고
TSP 알고리즘
- 모든 도시를 한번씩 방문하고 여행을 시작한 원래 도시로 돌아올 수 있는 최단 거리를 구하는 알고리즘
- 비트 마스킹, dfs, dp 를 활용하여 푸는 문제
- 완전 탐색으로 풀 경우 시간 복잡도 O(N!)으로 시간초과 발생
- 출발지로 다시 돌아오므로 사이클이 형성되기 때문에 시작점은 어디든 상관없다.
- 비트 마스킹을 통해 방문 체크를 해준다.
- DFS를 통해 가장 적은 비용의 경로를 탐색한다.
- DP를 통해 시간 복잡도를 줄인다. DP를 활용하면 이전에 계산했던 경로를 다시 계산하지 않아도 된다.
visited[i][j] 는 i번 도시에서 visited에 표시된 도시들을 방문하지 않고 시작도시로 왔을 때의 최단 경로
import sys
input = sys.stdin.readline
n = int(input())
graph = []
for _ in range(n):
graph.append(list(map(int,input().split())))
# n개의 비트를 모두 켠다는 의미
VISITED_ALL = (1<<n)-1
# n번 -> visited에서 방문하지 않은 도시 -> 0번 도시(시작도시) 경로
cache = [[None] * (1<<n) for _ in range(n)]
INF = float('inf')
index = 1
def find_path(last, visited):
# 모든 경로를 다 돌았을 때 -> 즉 출발 위치를 0으로 정했으므로 현재 위치에서 0 으로 갈 때
if visited == VISITED_ALL :
# 경로가 존재하면 경로 리턴, 아니면 INF
return graph[last][0] or INF
# 이미 수행되었다는 뜻
if cache[last][visited] is not None:
return cache[last][visited]
tmp = INF
for c in range(n):
# 다음 도시로 가능 비용이 존재하고, 해당 도시를 방문하지 않았으면
if visited & (1<<c) == 0 and graph[last][c] != 0:
# 최솟값 갱신
tmp = min(tmp, find_path(c, visited | (1<<c)) + graph[last][c])
cache[last][visited] = tmp
return tmp
# 임의의 출발 도시 0에서 시작
print(find_path(0, 1<<0))
- 꼭 다시 풀기
'개발 > algorithm' 카테고리의 다른 글
[백준 1956번] 운동 - python (0) | 2022.05.06 |
---|---|
[백준 1520번] 내리막길 - python (0) | 2022.05.06 |
[백준 1057번] 토너먼트 - Python (0) | 2022.05.06 |
[프로그래머스][level3] 블록 이동하기 - python (0) | 2022.05.05 |
[백준 1068번] 트리 - python (0) | 2022.04.29 |