1. 程式人生 > >最短Hamilton路徑

最短Hamilton路徑

led def bits () clu gif nbsp 後者 typedef

題目描述

給定一張 n(n≤20) 個點的帶權無向圖,點從 0~n-1 標號,求起點 0 到終點 n-1 的最短Hamilton路徑。 Hamilton路徑的定義是從 0 到 n-1 不重不漏地經過每個點恰好一次。

輸入

第一行一個整數n。
接下來n行每行n個整數,其中第i行第j個整數表示點i到j的距離(一個不超過10^7的正整數,記為a[i,j])。
對於任意的x,y,z,數據保證 a[x,x]=0,a[x,y]=a[y,x] 並且 a[x,y]+a[y,z]>=a[x,z]。

輸出

一個整數,表示最短Hamilton路徑的長度。

樣例輸入

4
0 2 1 3
2 0 2 1
1 2 0 1
3 1 1 0

樣例輸出

4

提示

從0到3的Hamilton路徑有兩條,0-1-2-3和0-2-1-3。前者的長度為2+2+1=5,後者的長度為1+2+1=4

基礎的狀態壓縮DP 每個點有兩種狀態,可以放和不可以放,可以放牧用1表示,否則用0表示。 【狀態】【位置】 所以共有15種狀態 從0出發,所以初始是dp[i][j]=mapp[0][j]; 狀態轉移:dp[i][j]=min(dp[i][j],dp[i-temp][k]+mapp[k][j]); 技術分享圖片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int mapp[25][25]; int dp[1<<20][25]; const int inf=1e9; int main(){ ios::sync_with_stdio(false); int n; cin>>n; for(int i=0;i<n;i++){ for(int j=0;j<n;j++) cin>>mapp[i][j]; } int sum=(1<<n)-1; for(int i=1;i<=sum;i++){ for(int j=0
;j<n;j++){ int temp=(1<<j); if(i&temp){ if(i==temp){ dp[i][j]=mapp[0][j]; } else{ dp[i][j]=inf; for(int k=0;k<n;k++){ if(i&(1<<k)&&j!=k) dp[i][j]=min(dp[i][j],dp[i-temp][k]+mapp[k][j]); } } } } } cout<<dp[sum][n-1]<<endl; return 0; }
View Code

最短Hamilton路徑