1. 程式人生 > 實用技巧 >16.最短Hamilton路徑 狀態壓縮DP

16.最短Hamilton路徑 狀態壓縮DP

這道題目其實我也不會,第一次學習只是有個模糊的框架

之後還需要複習

需要配合一丟丟圖論的基礎知識,涉及到的不多

暴力做法時間複雜度就是階乘級別的

依然是用狀態壓縮DP

用一個整數表示一個狀態

每個點只能走一次

dp[i][j]中的i就是壓縮後的一個狀態

i這個二進位制數中的每一位分別表示當前這個點是否走過了

比如說i = 1110011時

從右到左看,就表示

0號點已經走過了

1號點已經走過了

2號點沒有走過

3號點沒有走過

4號點已經走過了

5號點已經走過了

6號點已經走過了

集合劃分:根據倒數第二個點是哪個點來分類

 1 #include <bits/stdc++.h>
 2 using
namespace std; 3 const int N = 21, M = (1 << N); 4 int w[N][N]; //兩點之間的距離 5 int dp[M][N]; 6 int main() { 7 int n; 8 cin >> n; 9 for (int i = 0; i < n; i++) { 10 for (int j = 0; j < n; j++) { 11 cin >> w[i][j]; 12 } 13 } 14 memset(dp, 0x3f
, sizeof dp); //求最小值要初始化為一個較大值 15 dp[1][0] = 0; //邊界值 16 for (int i = 0; i < (1 << n); i++) { //所有狀態 17 for (int j = 0; j < n; j++) { //所有點 18 if (i >> j & 1) { 19 for (int k = 0; k < n; k++) { //列舉下從哪個點轉移過來 20 if (i >> k & 1
) { //從k點轉移過來 21 dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + w[k][j]); 22 } 23 } 24 } 25 } 26 } 27 cout << dp[(1 << n) - 1][n - 1] << endl; 28 return 0; 29 }