POJ 3311 Hie with the Pie
题意:有n+1个地方需要送馅饼,但是只有一个送货员,然后给出每个点到其他n个点的时间,然后找最有方案,
思路:与前两个状压dp不一样,是一个TSP问题。挑战程序设计上面的例题就是一道TSP的问题,不一样的地方就是,在找路径之前,需要用floyd把所有路径都更新为最短路径。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f
typedef long long LL;
int n;
int dp[1<<12][20];
int mapp[12][12];
int main()
{
while(scanf("%d",&n)!=EOF,n)
{
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
scanf("%d",&mapp[i][j]);
for(int k=0; k<=n; k++)
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
mapp[i][j]=min(mapp[i][j],mapp[i][k]+mapp[k][j]);
for(int s=0; s<=(1<<n)-1; s++) //先对1~n 的点枚举
{
for(int i=1; i<=n; i++)
{
if(s&(1<<(i-1))) // 如果情况i在集合s中
{
if(s == (1<<(i-1))) //如果当前的集合s与情况i相同,最有解是从0出发到达i,也是dp的边界情况
dp[s][i]=mapp[0][i];
else
{
dp[s][i]=inf;
for(int j=1; j<=n; j++)
{
if(s & (1<<(j-1)) && i!=j) //枚举不是城市I的其他城市
{
dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+mapp[j][i]);
//在没经过城市i的状态中,寻找合适的中间点j使得距离更短
}
}
}
}
}
}
int ans=inf;
// 找到从1~n的最短路之后,然后从每个点返回到0的距离
for(int i=1; i<=n; i++)
{
ans=min(ans,dp[(1<<n)-1][i]+mapp[i][0]);
}
printf("%d
",ans);
}
return 0;
}