版权声明:点个关注(^-^)V https://blog.csdn.net/weixin_41793113/article/details/89738459
题目链接:http://poj.org/problem?id=3311
描述 Pizazz Pizzeria以其尽快为客户提供比萨饼而自豪。不幸的是,由于削减,他们只能雇用一名司机来完成交付。在开始任何交付之前,他将等待处理1个或更多(最多10个)订单。毋庸置疑,他希望采用最短的路线送上这些好吃的东西,然后回到比萨店,即使这意味着途中不止一次经过同一地点或比萨店。他委托你写一个程序来帮助他。 输入 输入将包含多个测试用例。第一行包含一个整数Ñ指示交付的订单数量,其中1≤ ñ ≤10.在此之后将是Ñ + 1行,每行含有Ñ + 1点的整数指示倍比萨饼之间行进(编号0)和n个位置(数字1到n)。第i行的第j个值表示直接从位置i到达位置j的时间,而不会访问沿途的任何其他位置。请注意,从i到j可能有更快捷的方法通过其他位置,由于不同的速度限制,交通信号灯等。此外,时间值可能不对称,即,直接从位置i到j的时间可能与直接从位置的时间不同Ĵ给我。输入值n = 0将终止输入。 产量 对于每个测试用例,您应输出一个数字,表示交付所有比萨饼并返回比萨饼店的最短时间。 样本输入 样本输出 资源 |
题意:就是批萨点小二要送批萨,然后给你每个点的距离,有向的,然后让你就走一次回到原点的最短路。
分析:因为给出的是稠密图,所以要处理一下最短路,floyd
然后TSP就好。
枚举每个状态,对于当前状态的每一个已经走过的点,枚举是从那个点走过来的,更新最短路
状态:dp[s][i] :s状态下走到点 i 的最短路
转移方程:dp[s][i]=min(dp[s^(1<<i)][j]+mp[j][i],dp[s][i]);
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX = 11;
const int INF = 99999999;
int dis[MAX][MAX],dp[1<<MAX][MAX];
int n;
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]);
for(int k=0;k<=n;k++)//floyd
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
if(dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j] = dis[i][k]+dis[k][j];
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)))//边界情况,s只含一个1,说明起点只能是0
dp[s][i] = dis[0][i];
else{
dp[s][i] = INF;
for(int j=1;j<=n;j++)
if(s&(1<<(j-1)) && i!=j)
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);
}
return 0;
}