
풀이.
비트마스킹을 이용해서 풀어야한다.
비트마스킹의 장점은 다음과 같이 3가지가 있다.
1. 빠른 수행시간
- 2진수를 이용하기에 연산속도가 빠르다
2. 적은 메모리
- [1, 1, 0, 0, 1, 1, 1] 같은 방문을 체크하는 배열을 1100111과 같은 이진수로 표현이 가능하다
3. 짧고 깔끔한 코드
우선 문제에서 살펴봐야하는 것은 도시에서 도시끼리의 길에 가중치가 있고 경로가 없을 수 있다는 것 그리고 처음의 경로로 돌아와야한다는 것이다.
즉 출발 지점에서 출발지점으로 돌아와야하므로 순환을 이룬다는 것이다.
또한 경로가 같으면 어떤 도시에서 출발하더라고 순회 비용은 동일하므로 무조건 0에서 출발하여 가장 작은 순회 비용을 구하면 된다.
소스코드.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
def dfs(x, visited): | |
# 도시를 모두 순환했을 때 | |
if visited == (1 << (n-1)) -1: | |
if matrix[x][0]: | |
return matrix[x][0] | |
else: | |
return inf | |
if dp[x][visited] != -1: | |
return dp[x][visited] | |
dp[x][visited] = inf | |
for i in range(1, n): | |
# x 에서 i로 가는 경로가 없을 경우 | |
if not matrix[x][i]: | |
continue | |
# i에 이미 방문했을 경우 | |
if visited & ( 1 << i -1 ): | |
continue | |
dp[x][visited] = min(dp[x][visited], dfs(i, visited | (1 << (i-1))) + matrix[x][i]) | |
return dp[x][visited] | |
input = sys.stdin.readline | |
inf = float('inf') | |
n = int(input()) | |
matrix = [] | |
for i in range(n): | |
matrix.append(list(map(int, input().split()))) | |
dp = [[-1] * (1 << n) for i in range(n)] | |
print(dfs(0, 0)) |
'프로그래밍 > 백준' 카테고리의 다른 글
[백준] 2357 최솟값과 최댓값 - 파이썬 (0) | 2021.09.14 |
---|---|
[백준] 11505 구간 곱 구하기 - 파이썬 (0) | 2021.09.14 |
[백준] 파이썬 2042 - 구간 합 구하기 (0) | 2021.09.12 |
[백준] 11659 구간 합 구하기 4 - 파이썬 (0) | 2021.08.23 |
백준 2252 줄 세우기 - 파이썬 (0) | 2021.08.06 |