POJ_3311_Hie with the Pie(floyd+状态压缩)

来源:互联网 发布:数据爬虫工程师 编辑:程序博客网 时间:2024/06/16 07:39

题型:图论+DP


题意:求从起点经过每一个点再回到起点的最短路。


分析:

INPUT给出的是邻接矩阵,就顺势做一个Floyd,就出任意两点之间的最短路。

由于只有10个点,采用状态压缩,二进制枚举到达的城市,并再用一维标记当前抵达的城市。

设dp(i,j)表示i状态时到达j城市的最短路,i为二进制串,其中的1表示已经过的城市。

然后枚举i二进制串中的0,将其改为1从而得到下一个状态。


代码:

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#define INF 0x3f3f3f3f#define mt(a,b) memset(a,b,sizeof(a))using namespace std;int n;int dist[20][20];int dp[2000][15];void floyd() {    for(int k=0; k<=n; k++) {        for(int i=0; i<=n; i++) {            for(int j=0; j<=n; j++) {                if(dist[i][k]+dist[k][j]<dist[i][j]) {                    dist[i][j] = dist[i][k] + dist[k][j];                }            }        }    }}int main() {    while(1) {        scanf("%d",&n);        if(n==0) return 0;        int gx;        for(int i=0; i<=n; i++) {            for(int j=0; j<=n; j++) {                scanf("%d",&dist[i][j]);            }        }        floyd();        mt(dp,INF);//        for(int i=0;i<=n;i++){//            for(int j=0;j<=n;j++){//                printf("%4d ",dist[i][j]);//            }//            puts("");//        }        for(int i=0; i<=n; i++) {            dp[1<<i][i] = 0;        }        int big = (1<<n);        for(int i=0; i<big; i++) {            for(int pos=1; pos<=n; pos++) {                if(i == (1<<(pos-1))){                    dp[i][pos] = dist[0][pos];                }                else{                    for(int j=1;j<=n;j++){                        if((i&(1<<(j-1))) && (j != pos)){                            dp[i][pos] = min(dp[i][pos],dp[(1<<(pos-1))^i][j]+dist[j][pos]);                        }                    }                }            }        }        int ans = INF;        for(int i=1;i<=n;i++){            ans = min(ans,dp[big-1][i]+dist[i][0]);            //printf("%d ",dp[big-1][i]);        }        //puts("");        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击