POJ 3311 Hie with the Pie floyd+状压DP

来源:互联网 发布:qq音乐数据库 api接口 编辑:程序博客网 时间:2024/06/04 11:10

链接:http://poj.org/problem?id=3311

题意:有N个地点和一个出发点(N<=10),给出所有地点两两之间的距离,问从出发点出发,走遍所有地点再回到出发点的最短距离是多少。

思路:首先用floyd找到所有点之间的最短路。然后用状态压缩,dp数组一定是二维的,如果是一维的话不能保证dp[i]->dp[j]一定是最短的。因为dp[i]记录的“当前位置”不一定是能使dp[j]最小的当前位置。所以dp[i][j]中,i表示的二进制下的当前已经经过的状态,j表示的是在当前状态下目前所在的位置。

代码:

#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <ctype.h>#include <iostream>#include <map>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define eps 1e-8#define INF 0x7fffffff#define PI acos(-1.0)#define seed 31//131,1313#define maxn 15typedef long long LL;typedef unsigned long long ULL;using namespace std;int dp[1<<10][maxn];int Pow[maxn];int back[maxn];int cost[maxn][maxn];void init1(){    Pow[0]=1;    for(int i=1; i<=10; i++)        Pow[i]=Pow[i-1]*2;}void init2(){    for(int i=1; i<(1<<10); i++)        for(int j=0; j<=10; j++)            dp[i][j]=INF;}int floyd(int a[][maxn],int t){    for(int i=0; i<t; i++)        for(int j=0; j<t; j++)            for(int k=0; k<t; k++)                a[i][j]=min(a[i][k]+a[k][j],a[i][j]);}int main(){    int T,x;    init1();    while(scanf("%d",&T))    {        init2();        if(!T)            break;        for(int i=0; i<T+1; i++)            for(int j=0; j<T+1; j++)                scanf("%d",&cost[i][j]);        floyd(cost,T+1);        for(int i=0; i<T; i++)            dp[Pow[i]][i]=cost[0][i+1];        for(int i=0; i<T; i++)            back[i]=cost[i+1][0];        for(int i=0; i<T; i++)            for(int j=0; j<T; j++)                cost[i][j]=cost[i+1][j+1];        for(int i=0; i<(1<<T); i++)        {            if(i==1||i==2||i==4||i==8||i==16||i==32||i==64||i==128||i==256||i==512)            continue;            int ii=i;            int pos=0;            while(ii)            {                if(ii%2==1)                {                    int t=i-Pow[pos];                    for(int j=0; j<T; j++)                        if(dp[t][j]!=INF&&dp[t][j]+cost[j][pos]<dp[i][pos])                            dp[i][pos]=dp[t][j]+cost[j][pos];                }                ii>>=1;                pos++;            }        }        int ans=INF;        for(int i=0; i<T; i++)        {            if(dp[(1<<T)-1][i]!=INF&&dp[(1<<T)-1][i]+back[i]<ans)                ans=dp[(1<<T)-1][i]+back[i];        }        printf("%d\n",ans);    }    return 0;}


2 0
原创粉丝点击