poj传送门
经典TSP问题,可以使用状态压缩完成。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define ms(i,j) memset(i,j, sizeof i);
using namespace std;
const int MAXN = 10 + 5;
const int Zinf = 100000000;
int dis[MAXN][MAXN];
int dp[1<<MAXN][MAXN];//dp[i][j]为在i状态下访问到j结点时的最优解
int n;
void floyd()
{
for (int k=0;k<=n;k++)
for (int i=0;i<=n;i++)
for (int j=0;j<=n;j++)
if (i!=j&&i!=k&&k!=j)
{
dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j]);
}
}
int main()
{
while(scanf("%d",&n) && n)
{
ms(dis, 127);
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
scanf("%d",&dis[i][j]);
floyd();
for (int S=0;S<=(1<<n)-1;S++)//枚举每个状态。fix:从0开始
{
for (int i=1;i<=n;i++)//枚举每个点
{
if (S & (1<<(i-1)))//这个点在S中(已被访问)
{
if (S==(1<<(i-1)))//如果S只访问了i
{
dp[S][i] = dis[0][i];//动归边界
} else
{
dp[S][i] = Zinf;
for (int j=1;j<=n;j++)//找访问过的点且这个点不是i
{
if (i!=j && (S & (1<<(j-1))))
{
dp[S][i] = min(dp[S][i], dp[S^(1<<(i-1))][j]+dis[j][i]);
//找中间点更新值,类似floyd
}
}
}
}
}
}
int ans = Zinf;
for (int i=1;i<=n;i++)
{
ans = min(ans, dp[(1<<n)-1][i] + dis[i][0]);//fix:是(1<<n)-1 ,不是1<<(n-1),小心!
}
printf("%d\n", ans);
}
return 0;
}