题目大意:
输入一个整数n,代表除送餐开始地(0)以外必须要送达的n个地方,然后下面n+1行,然后第i行第j个数表示从i到j要花的时间,然后问题是到达所有送餐地并回到初始位置的最短时间,到达某个餐馆次序不一定;
基本思路:
从某一个地点到另一个地点,然后有许多种情况,只能挨个枚举,然后当前所有到达的地点形成一个状态s,然后dp【s】【i】就是当前状态为s,当前到达地点为i的最短时间;然后就是异或运算符的使用,就是每一位异或1取反异或0不变,然后枚举每一个当前状态然后枚举每一个当前到达的位置i(相当于所有已经到达的点的信息都存在了s中),然后枚举每一个位置j,表示从位置j到打位置i的最短时间,这样就枚举完了所有的情况;
代码如下:
#include<iostream>
#include<iomanip>
#include<string>
#include<queue>
#include<map>
#include<list>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int inf = 0x3f3f3f3f;
int dp[1<<11][15];
int gra[15][15];
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
scanf("%d",&gra[i][j]);
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++)
if(gra[j][k]>gra[j][i]+gra[i][k])
gra[j][k]=gra[j][i]+gra[i][k];
int maxx=1<<n;
for(int s=0;s<maxx;s++)
{
for(int i=1;i<=n;i++)
{
if(s&(1<<(i-1)))//首先s这个状态得已经走过i才行;
{
if(s==(1<<(i-1)))
dp[s][i]=gra[0][i];
else
{
dp[s][i]=inf;
for(int j=1;j<=n;j++)//从哪一个位置走到的i;
{
if((s&(1<<(j-1)))&&i!=j)
dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+gra[j][i]);
}
}
}
}
}
int ans=inf;
for(int i=1;i<=n;i++)
{
ans=min(ans,dp[maxx-1][i]+gra[i][0]);
}
printf("%d\n",ans);
}
return n;
}