题目链接:点击打开链接
题意:大致就是邮递员要从0号 送快件,一共有n个地方,要求从0开始走完所有的节点在回到0的最短路径。先用Floyd跑出来最短路,然后就是一个裸TSP问题了
TSP:顾名思义,旅行商问题,就是从起点出发遍历n个城市在回到起点的最短路径,在n比较小的情况下状压是个比较好的办法,二进制0代表没访问该城市,反之亦然。所以一共有 2^n-1种状态, 设 dp[s][i] 代表当前状态为s 当前所在城市节点为i dp[s][i]=min(dp[s][i] ,dp[s'][j]+dis[j][i]) (从当前状态中去掉i 然后从其他的已经访问过的节点中更新dp[s][i])
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define maxn 1<<11
#define Mod 1000000007
#define ll long long
#define _ll __int64
#define ull unsigned long long
using namespace std;
int n,dis[15][15],dp[maxn][15];
void Floyd()
{
for(int k=0; k<=n; k++)
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
dis[i][j]=min(dis[i][j],dis[i][k] +dis[k][j]);
}
void solve()
{
int tot=(1<<n)-1;
for(int s=0; s<=tot; s++)
{
for(int i=1; i<=n; i++)
{
if(s&(1<<(i-1)))
{
if(s==(1<<(i-1)))
dp[s][i]=dis[0][i];
else
{
dp[s][i]=INF;
for(int j=1; j<=n; j++)
if(s&(1<<(j-1)) && j!=i)
dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+dis[j][i]);
}
}
}
}
int ans=INF;
for(int i=1; i<=n; i++)
ans=min(ans,dp[tot][i]+dis[i][0]);
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
scanf("%d",&dis[i][j]);
Floyd();
solve();
}
return 0;
}