포스트

[백준][2098] 외판원 순회

이 포스트는 백준 사이트의 외판원 순회 문제 풀이입니다.

문제

문제


해결 과정

이 문제는 비트마스킹과 메모이제이션 기법을 사용하면 제한시간 안에 결과를 확인할 수 있습니다.

문제가 요구하는 결과는 모든 지점을 방문할 때, 비용의 최솟값입니다.
이 값을 구하기 위해 모든 지점에서 매번 새롭게 비용을 구한다면
시간초과로 인해서 제한시간 안에 해결할 수 없습니다.

따라서 실행 시간을 단축시키기 위해
모든 도시를 재방문하지 않고 최초 1회만 방문하여 최솟값을 구하고자 하였습니다.
그리고 재방문 기록을 위해서는 boolean 배열이 아니라 비트 연산자를 사용해 보았습니다.

코드 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>

using namespace std;

int N;
int DP[16][1 << 16];	//: [현재 도시 위치][방문했던 도시를 비트마크로]
int cost_map[16][16];	//: (N x N) 형식 비용 표

int TSP(int curr, int visited);


int main(){
	ios::sync_with_io(false);
	cin.tie(0);

	cin >> N;

	for (int start = 0, cost; start < N; ++start)
	{
		for (int end = 0; end < N; ++end)
		{
			cin >> cost;
			cost_map[start][end] = cost;
		}
	}

	cout << TSP(0, 1);
	return 0;
}


int TSP(int curr, int visited) {		// curr: 시작위치, visited: bit로 표현한 방문기록
	if (visited == ((1 << N) - 1)) {	// 모든 도시 방문 완료.
		if (0 == cost_map[curr][0])		// 현위치에서 0번으로 돌아갈 수 없음.
			return 2e9;
		else
			return cost_map[curr][0];	// 돌아갈 수 있음.
	}
	
	if (false != DP[curr][visited])	// 이미 방문함.
		return DP[curr][visited];

	DP[curr][visited] = 2e9;	// 첫 방문이므로 최소비용 비교를 위해 최댓값 초기화.

	// bit masking을 사용해 0번부터 N - 1번 노드까지
	// 현재 위치랑 연결되어 있는지 확인
	for (int bit_mask = 0; bit_mask < N; ++bit_mask) {
		int next = 1 << bit_mask;

		// 연결(curr->bit_mask)이 안됨 || 이미 방문 했었음.
		if ((0 == cost_map[curr][bit_mask]) || (0 < (visited & next)))
			continue;

		// 현재 노드에서 visited에 비트로 작성된 도시 방문 중 최소값
		DP[curr][visited] = min(
			DP[curr][visited], 
			TSP(bit_mask, visited | next) + cost_map[curr][bit_mask]
		);
	}

	return DP[curr][visited];
}


실행 결과

결과


이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.