poj3311 Hie with the Pie Floyd+状压dp 简单TSP问题

版权声明:点个关注(^-^)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的时间,而不会访问沿途的任何其他位置。请注意,从ij可能有更快捷的方法通过其他位置,由于不同的速度限制,交通信号灯等。此外,时间值可能不对称,即,直接从位置ij的时间可能与直接从位置的时间不同Ĵ。输入值n = 0将终止输入。

产量

对于每个测试用例,您应输出一个数字,表示交付所有比萨饼并返回比萨饼店的最短时间。

样本输入

3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0

样本输出

8

资源

2006年北美东部中部

题意:就是批萨点小二要送批萨,然后给你每个点的距离,有向的,然后让你就走一次回到原点的最短路。

分析:因为给出的是稠密图,所以要处理一下最短路,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;
}

猜你喜欢

转载自blog.csdn.net/weixin_41793113/article/details/89738459