【HDOJ 5418】 Victor and World (状压dp)
旅行商问题 不要害怕 只有16个点 所以用状压即可 floyd初始化各点最小距离 然后枚举状态 dp该状态下包含的点 dp最短距离
最后dp一下每个点在全1状态下的最短距离 即为绕一圈回来后的最短距离
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; #define ll long long #define INF 0x3f3f3f3f int mp[16][16]; int dp[16][1<<16]; int main() { // freopen("../../../in.in","r",stdin); int t,n,m,u,v,w,i,j,k; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); memset(mp,INF,sizeof(mp)); while(m--) { scanf("%d %d %d",&u,&v,&w); if(mp[u-1][v-1] > w) mp[u-1][v-1] = mp[v-1][u-1] = w; } for(k = 0; k < n; ++k)//floyd求多源最短路 for(i = 0; i < n; ++i) for(j = 0; j < n; ++j) mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]); memset(dp,INF,sizeof(dp)); dp[0][1] = 0;//初始化0000000001状态 for(i = 1; i < (1<<n); ++i)//枚举状态 for(j = 0; j < n; ++j)//枚举起点 if((1<<j)&i) for(k = 0; k < n; ++k)//枚举终点 if((1<<k)&i) dp[j][i] = min(dp[j][i],dp[k][i^(1<<j)]+mp[j][k]); for(i = 1; i < n; ++i)//找全局最短 { dp[0][(1<<n)-1] = min(dp[0][(1<<n)-1],dp[i][(1<<n)-1]+mp[i][0]); } printf("%d\n",dp[0][(1<<n)-1]); } return 0; }