题目:http://www.gdfzoj.com/oj/contest/270/problems/1
有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的时间。(n<=15)
看到数据范围容易想到状压
看看题目好像可以状压~
。
。
。
qtmd!!!
题目给的数据不是最短路径!!!
得记最短路径!!!
n<=15嘛
floyd咯~
void floyd()
{
int i,j,k;
for (i=0;i<=n;i++)
for (j=0;j<=n;j++)
for (k=0;k<=n;k++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
算出最短路之后呢~
突然想到个问题:
如果你走最短路之一1->2->3
然而你状态只记录了首末1,3!!!2呢???!!!
这问题想了好久终于想出来了。。。
你走1->2->3 则一定有1->2 1->3为最短路
那么
你的状态min一定记录的是走过1->2 1->3 的状态
这里好好琢磨琢磨就懂了~
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n;
int dis[20][20],f[1<<16][20];
void floyd()
{
int i,j,k;
for (i=0;i<=n;i++)
for (j=0;j<=n;j++)
for (k=0;k<=n;k++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
int i,j,k,s;
freopen("a.txt","r",stdin);
scanf("%d",&n);
for (i=0;i<=n;i++)
for (j=0;j<=n;j++)
scanf("%d",&dis[i][j]);
floyd();
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for (s=1;s<(1<<(n+1));s++)//当前状态
{
for (i=0;i<=n;i++)
{
if ((s&(1<<i))==0)
continue;
for (j=0;j<=n;j++)
{
if (j!=0&&(s&(1<<j))==0)
continue;
f[s][i]=min(f[s][i],f[s-(1<<i)][j]+dis[i][j]);
}
}
}
printf("%d",f[s-1][0]);
return 0;
}