经典TSP变形
学到:1、floyd O(n^3)处理随意两点的最短路
2、集合的位表示,我会在最后的总结出写出。注意写代码之前一定设计好位的状态。本题中,第0位到第n位分别代表第i个城市,1是已经走过,0没走过
那么DP方程 :dp[s][i]--当前在城市i。状态为s(s存储的是走过了那些城市)
3、最后要求形成回路,那么就是min(dp[1<<(n+1)-1][i],dp[0][i])
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <cmath> #include <map> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) const int MAXN = 12; int dis[MAXN][MAXN]; int dp[1<<MAXN][MAXN]; const int INF = 1e9+10; int n; void floyd() { rep(k,0,n+1) rep(i,0,n+1) rep(j,0,n+1) dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); } int main() { //IN("poj3311.txt"); int len; while(~scanf("%d",&n) && n) { rep(i,0,n+1) rep(j,0,n+1) dp[i][j]=dis[i][j]=INF; rep(i,0,n+1) rep(j,0,n+1) { scanf("%d",&len); dis[i][j]=min(dis[i][j],len); } floyd();//求出随意两点的距离 int S=1<<(n+1); rep(i,0,S) rep(j,0,n+1) { dp[i][j]=INF; } for(int s=0;s<S;s++)//枚举全部的状态 rep(i,0,n+1) { if(s&(1<<(i))) { if(s==(1<<i))dp[s][i]=dis[0][i]; else rep(j,0,n+1) if(s&(1<<j) && i!=j) { dp[s][i]=min(dp[s^(1<<i)][j]+dis[j][i],dp[s][i]); } } } int ans=INF; for(int i=0;i<n+1;i++) ans=min(ans,dp[(S-1)][i]+dis[i][0]); printf("%d ",ans); } return 0; }