【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;
}