【狀壓dp】【最短Hamilton路徑】
阿新 • • 發佈:2018-11-19
題意:
給出n個點,然後給出每兩個點之間的路徑,要求找到一條最短的路徑,從第1個點出發,到達最後一個點,中間所有的點都只經過一次,要求這條路徑是最短的。這稱為最短Hamilton路徑。
思路:
因為n只有20個點,所以考慮狀壓dp,每一個狀態由兩個資料組成,一個是這個狀態最後停在了哪個點,一個是這個狀態之前走過了哪些路徑。
用f[1<<20][20]來記錄這個狀態下已經走過的最短路徑。
那麼 f[i][j] = min{f[1<<j ^ i][k]+w[k][j]} 要求 k 和 j 這兩個點在 i 所記錄的路徑中出現過。
然後從第一個狀態不斷往後進行更新即可。
程式碼:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define rep(i,a,b) for(int i = a; i <= b; i++) using namespace std; int w[25][25],n; int f[1<<21][25]; void solve() { memset(f,0x3f,sizeof f); f[1][0] = 0; rep(i,0,(1<<n)-1) { rep(j,0,n-1) if(1<<j & i) //這個點被走過了,列舉結束點 rep(k,0,n-1) //由哪個點更新而來 if(1<<k & i) f[i][j] = min(f[i][j],f[i ^ 1<<j][k]+w[k][j]); } printf("%d\n",f[(1<<n)-1][n-1]); } int main() { while(~scanf("%d",&n)) { rep(i,0,n-1) rep(j,0,n-1) scanf("%d",&w[i][j]); solve(); } return 0; }