|
1 | 1 | ---
|
2 |
| -created: 2025/5/07 14:29:20 |
3 |
| -modified: 2025/5/07 14:32:10 |
| 2 | +description: |
| 3 | +aliases: |
| 4 | + - tsp |
| 5 | +created: 2025-05-18 |
| 6 | +modified: 2025-07-04 |
4 | 7 | ---
|
| 8 | +- TSP is a touchstone for many general heuristics devised for combinatorial optimization such as [genetic algorithms](https://en.wikipedia.org/wiki/Genetic_algorithm "Genetic algorithm"), [simulated annealing](https://en.wikipedia.org/wiki/Simulated_annealing "Simulated annealing"), [tabu search](https://en.wikipedia.org/wiki/Tabu_search "Tabu search"), [ant colony optimization](https://en.wikipedia.org/wiki/Ant_colony_optimization "Ant colony optimization"), [river formation dynamics](https://en.wikipedia.org/w/index.php?title=River_formation_dynamics&action=edit&redlink=1 "River formation dynamics (page does not exist)") (see [swarm intelligence](https://en.wikipedia.org/wiki/Swarm_intelligence "Swarm intelligence")), and the [cross entropy method](https://en.wikipedia.org/wiki/Cross_entropy_method "Cross entropy method"). |
| 9 | +- DP (recursive) |
5 | 10 | - DP + Bit mask
|
6 |
| -- `dp[current][visited]` |
7 |
| - - 현재 도시가 current이고, visited는 지금까지 방문한 도시의 집합 |
8 |
| - - visited는 비트마스크 (0 ~ 2ⁿ - 1)로 표현 |
9 |
| - - ```peusudo |
10 |
| - function tsp(current, visited): |
11 |
| - // 모든 조합이라는 것은 다 돌았다는 뜻 |
12 |
| - if visited == all_visited_mask((1 << N) - 1): |
13 |
| - // 마지막에서 처음으로 가는 비용이 있다는 것은 돌아 갈 수 있다는 말 |
14 |
| - if cost[current][start] > 0: |
15 |
| - return cost[current][start] // 돌아가는 비용 |
16 |
| - else: |
17 |
| - // 돌아가지 못함으로 |
18 |
| - return INF // 못 돌아감 |
19 |
| - |
20 |
| - // 이미 구한 값이 있으면 얼리 리턴 (not initial value ex: -1) |
21 |
| - if dp[current][visited] is already computed: |
22 |
| - return dp[current][visited] |
23 |
| - |
24 |
| - dp[current][visited] = INF |
25 |
| - |
26 |
| - // 모든 도시에 대해서 |
27 |
| - for next in 0 to N-1: |
28 |
| - // 조합에 없는 도시만 비트마스크로 추출, 거리가 있다면 dp 없데이트 |
29 |
| - if city 'next' is not visited and cost[current][next] > 0: |
30 |
| - dp[current][visited] = min( |
31 |
| - dp[current][visited], |
32 |
| - tsp(next, visited | (1 << next)) + cost[current][next] |
33 |
| - ) |
34 |
| - |
35 |
| - return dp[current][visited] |
36 |
| -- 전이 공식 |
37 |
| - - `mask`: 방문한 도시 집합 |
38 |
| - - `last`: 마지막 방문 도시 |
39 |
| - - `dp[mask][last]` = mask를 돌고 last에서 끝날 때 최소 비용 |
40 |
| - - ```cpp |
41 |
| - dp[1<<0][0] = 0; |
42 |
| - for(mask = 0 ; mask < 1<<N; mask++) |
43 |
| - for(last = 0; last < N; last++){ |
44 |
| - if(!(mask & 1 << last)) continue; |
45 |
| - for(next = 0; next < N; next++){ |
46 |
| - if(mask & 1 << next) continue; |
47 |
| - newMask = mask | (1<<next); |
48 |
| - dp[newMask][next] = min( |
49 |
| - dp[newMask][next], |
50 |
| - dp[mask][last] + dist[last][next] |
51 |
| - ); |
52 |
| - } |
53 |
| - } |
| 11 | + - Held-Karp 알고리즘 |
| 12 | + - `dp[current][visited]` |
| 13 | + - 현재 도시가 current이고, visited는 지금까지 방문한 도시의 집합 |
| 14 | + - visited는 비트마스크 (0 ~ 2ⁿ - 1)로 표현 |
| 15 | + - ```peusudo |
| 16 | + function tsp(current, visited): |
| 17 | + // 모든 조합이라는 것은 다 돌았다는 뜻 |
| 18 | + if visited == all_visited_mask((1 << N) - 1): |
| 19 | + // 마지막에서 처음으로 가는 비용이 있다는 것은 돌아 갈 수 있다는 말 |
| 20 | + if cost[current][start] > 0: |
| 21 | + return cost[current][start] // 돌아가는 비용 |
| 22 | + else: |
| 23 | + // 돌아가지 못함으로 |
| 24 | + return INF // 못 돌아감 |
| 25 | + |
| 26 | + // 이미 구한 값이 있으면 얼리 리턴 (not initial value ex: -1) |
| 27 | + if dp[current][visited] is already computed: |
| 28 | + return dp[current][visited] |
| 29 | + |
| 30 | + dp[current][visited] = INF |
| 31 | + |
| 32 | + // 모든 도시에 대해서 |
| 33 | + for next in 0 to N-1: |
| 34 | + // 조합에 없는 도시만 비트마스크로 추출, 거리가 있다면 dp 없데이트 |
| 35 | + if city 'next' is not visited and cost[current][next] > 0: |
| 36 | + dp[current][visited] = min( |
| 37 | + dp[current][visited], |
| 38 | + tsp(next, visited | (1 << next)) + cost[current][next] |
| 39 | + ) |
| 40 | + |
| 41 | + return dp[current][visited] |
| 42 | + - 전이 공식 |
| 43 | + - `mask`: 방문한 도시 집합 |
| 44 | + - `last`: 마지막 방문 도시 |
| 45 | + - `dp[mask][last]` = mask를 돌고 last에서 끝날 때 최소 비용 |
| 46 | + - ```cpp |
| 47 | + dp[1<<0][0] = 0; |
| 48 | + for(mask = 0 ; mask < 1<<N; mask++){ |
| 49 | + for(last = 0; last < N; last++){ |
| 50 | + if(!(mask & 1 << last)) continue; // last가 이미 있다면 패스 |
| 51 | + |
| 52 | + for(next = 0; next < N; next++){ |
| 53 | + if(mask & 1 << next) continue; // next가 이미 있다면 패스 |
| 54 | + |
| 55 | + newMask = mask | (1<<next); |
| 56 | + |
| 57 | + dp[newMask][next] = min( |
| 58 | + dp[newMask][next], |
| 59 | + dp[mask][last] + dist[last][next] |
| 60 | + ); |
| 61 | + } |
| 62 | + } |
| 63 | + } |
0 commit comments