題目大意:給定一個 N 個點的無向圖,點有點權,求從 0 號點走到 N-1 號點的最短哈密頓路徑是多少。
題解:由於哈密頓路徑的定義是每個頂點必須經過且僅能經過一次,因此,可用當前是否經過了這些點和當前在哪個點來表示出一個狀態,則一共有 \(O(n2^n)\) 個狀態。考慮轉移方式,對於在 j 這個點的情況來說,可以從以下與 j 相鄰的節點 k 轉移來,k 必須滿足在當前狀態已經走到。因此,時間復雜度為 \(O(n^22^n)\)。
update at 2019.3.29
注意,由於狀態轉移方程為 $$dp[i][S]=min{dp[k][S']+dis(i,k)},k\in [1,n],S'\subset S$$,從中可以看出 i 的決策是不具有階段性的,即:i 並不是從小到大進行的,而對於集合來說是從小到大進行轉移的,因此應該以走過的點的集合作為階段,即:集合應該是循環的第一層。今天被這個搞到自閉了。。QAQ
代碼如下
#include <bits/stdc++.h>
using namespace std;
int dp[1<<20][20];
int n,G[20][20];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&G[i][j]);
memset(dp,0x3f,sizeof(dp));
dp[1][0]=0;
for(int i=1;i<1<<n;i++)
for(int j=0;j<n;j++)if(i>>j&1)
for(int k=0;k<n;k++)if((i^1<<j)>>k&1)
dp[i][j]=min(dp[i][j],dp[i^1<<j][k]+G[k][j]);
printf("%d\n",dp[(1<<n)-1][n-1]);
return 0;
}