본문 바로가기

백준 - 외판원 순회(2098) 본문

카테고리 없음

백준 - 외판원 순회(2098)

Seongjun_You 2024. 2. 11. 23:09

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

 

2098번: 외판원 순회

첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 16) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j

www.acmicpc.net

 

 

나에겐 어려운 문제였다.

계속 시간초과 나서 풀이를 확인했다.

시간초과를 해결하는게 핵심이었다.

 

data = []
n = int(input())
def dfs(cur_node, visited):
    if visited == pow(2, n)-1:
        if data[cur_node][0] != 0:
            return data[cur_node][0]
        else:
            return float('INF')

    if (visited, cur_node) in dp: # 1 2 3 4 5 1 경로와 1 3 2 4 5 1이 있을때 451이 겹침 이 부분은 값만 리턴
        print(visited, cur_node)
        return dp[(visited, cur_node)]
    min_cost = float('INF')
    for i in range(n):
        if (visited >> i) % 2 == 1 or data[cur_node][i] == 0:
            continue
        cost = dfs(i, visited | pow(2, i)) + data[cur_node][i]
        min_cost = min(cost, min_cost)
    dp[(visited, cur_node)] = min_cost
    return min_cost

for i in range(n):
    data.append(list(map(int, input().split())))

dp = {}
print(dfs(0, 1))
print(dp)

이동한 경로에 대해서는 list로 활용을 했으나 방문 검사를 하는데

많은 시간이 걸렸다.

그래서 비트마스킹을 이용했다.

 

dp리스트를 제거해도

정답은 똑같이 나온다

하지만 시간초과가 난다.

 

예를 들어

경로가

1 2 3 4 5 1

1 3 2 4 5 1

을 보면

4 5 1의 경로가 겹친다.

dp리스트에 4 5 1에 대한 코스트를 저장하면

굳이 탐색을 더 할필요가 없고 나중에 꺼내 쓰면 된다.

좋은 아이디어이다.

 

dp와 재귀 연습을 더 해야겠다.

Comments