今天在做枚举练习时,做到了此题。
链接:http://poj.org/problem?id=3311
此题大意是:给你一个有向加权图,问你如何从0点开始,以最小的时间遍历完所有点后,回到0点,整个过程路径可以重复走
一开始,我的弱智想法是,每到一个点就遍历所有点,后来发现根本找不到什么条件让这个结束,后来不经意间看到了Floyd算法,我突然想到,可以先用Floyd把任意两点间的有向最短距离求出来,用这个去遍历就可以避免考虑从一点到另一点的具体路径,反正肯定是选那个最短路径,只需要用dfs暴力枚举一下所有点的全排列即可。
代码如下:
//floyd弄出两点间的有向最短路径长度(经过此步就不用再担心该怎么枚举从一点走到另一点),然后
//只需要用dfs枚举所有可能路径就行
#include<stdio.h>
#include<string.h>
const int inf=0x0fffffff;
int Map[15][15],n,Min;
bool flag[15];
void floyd()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++)
if(Map[j][i]+Map[i][k]<Map[j][k])
Map[j][k]=Map[j][i]+Map[i][k];
}
void dfs(int m,int t,int level)
{
if(level==n)
if(Min>t+Map[m][0])
Min=t+Map[m][0];
for(int i=0;i<=n;i++)
{
if(flag[i]==false)
{
flag[i]=true;
dfs(i,t+Map[m][i],level+1);
flag[i]=false;
}
}
}
int main()
{
while(1)
{
scanf("%d",&n);
if(n==0)
break;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
scanf("%d",&Map[i][j]);
floyd();
memset(flag,false,sizeof(flag));
flag[0]=true;
Min=inf;
dfs(0,0,0);
printf("%d\n",Min);
}
return 0;
}