題目地址
求從點1出發經過其他點各一次再回到點1的最短路,即求哈密頓回路長度。
- 使用狀壓dp,定義dp[s][i]表示已訪問點的狀態為s,上一個訪問的點為i的最短路長度,然后枚舉上一個狀態和最后經過的點,再枚舉沒有在狀態中出現的中轉點,新狀態取個min。
- 如果不限制只經過每個點一次,可以先用floyd求一次多源最短路。
- 卡內存,可以用java或者用
vector<vector<int>> (N,vector<int>(M,INF));
code
#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int dis[22][22];
int n;
int main(){
scanf("%d",&n);
vector<vector<int>> dp(1<<(n),vector<int>(n+1,INF));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&dis[i][j]);
}
}
dp[1][1]=0;
for(int s=1;s<(1<<n);s++){
for(int i=1;i<=n;i++){
if(s&(1<<(i-1))){
for(int j=1;j<=n;j++){
if(!(s&(1<<(j-1)))){
int t=(s|(1<<(j-1)));
dp[t][j]=min(dp[t][j],dp[s][i]+dis[i][j]);
}
}
}
}
}
int ans=INF;
for(int i=2;i<=n;i++){
ans=min(ans,dp[(1<<n)-1][i]+dis[i][1]);
}
printf("%d\n",ans);
return 0;
}