牛客在线编程_毕业旅行问题
题目地址
求从点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;
}