POJ 3311 Hie with the Pie(状态压缩DP+Floyd)

来源:互联网 发布:爱奇艺会员 淘宝 编辑:程序博客网 时间:2024/05/20 05:10

Description
题意是有n个城市(1~n)和一个披萨店(0),要求一条回路,从0出发,又回到0,而且距离最短
Input
多组输入,每组用例第一行为一个整数n表示成熟数量,之后为一个(n+1)*(n+1)矩阵表示n个城市和披萨店之间的距离矩阵,以n=0结束输入
Output
对于每组用例,输出最短距离
Sample Input
3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0
Sample Output
8
Solution
TSP(旅行商)问题,首先不难想到用FLOYD先求出任意2点的距离dis[i][j],接着枚举所有状态,用11位二进制表示10个城市和披萨店,1表示经过,0表示没有经过 定义状态dp[state][j]表示在state状态下,到达城市I的最优值,接着状态转移方程:dp[state][i] = min{dp[s^(1<<(i-1)][k]) + dis[k][i],dp[state][i])},(state^(1<<(i-1))表示未到达城市i的所有状态,1<=k<=n)。对于全1的状态,即state=(1<< n)-1则表示经过所有城市的状态,最终还需要回到披萨店0,那么最终答案就是min{dp[state][i]+dis[i][0]}
Code

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define INF 1<<29int dp[(1<<11)+5][11];int main(){    int n;    while(scanf("%d",&n),n)    {        int dis[11][11];        for(int i=0;i<=n;i++)            for(int j=0;j<=n;j++)                scanf("%d",&dis[i][j]);        //Floyd求最短路         for(int k=0;k<=n;k++)            for(int i=0;i<=n;i++)                for(int j=0;j<=n;j++)                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);        memset(dp,0,sizeof(dp));//初始化         for(int state=0;state<(1<<n);state++)//枚举所有状态             for(int i=1;i<=n;i++)//枚举所有城市                 if(state&(1<<(i-1)))//去过i城市                 {                    if(state==(1<<(i-1)))//只去过i城市显然此状态最短路即为披萨店到i城市最短路                         dp[state][i]=dis[0][i];                    else//还去过其他城市                     {                        dp[state][i]=INF;//初始化                         //从此状态经过的其他城市中选取合适的中间点j城市使得总距离最小                         for(int j=1;j<=n;j++)                            if(i!=j&&state&(1<<(j-1)))                                dp[state][i]=min(dp[state][i],dp[state^(1<<(i-1))][j]+dis[j][i]);//更新最短总距离                     }                }        //从经过所有城市的状态中选取最短总距离         int ans=dp[(1<<n)-1][1]+dis[1][0];        for(int i=2;i<=n;i++)            ans=min(ans,dp[(1<<n)-1][i]+dis[i][0]);        printf("%d\n",ans);    }    return 0;}
0 0