poj3311 状态压缩dp

来源:互联网 发布:淘宝ulzzang短发女模特 编辑:程序博客网 时间:2024/05/20 03:08

比较经典的状态压缩dp,题目说了可以重复的走点,而且到一个点的最短路可能是通过其他的点间接到达,所以首先用Floyd处理一下,然后dp就可以了
状态转移公式

dp[i | (1<<(k-1))][k] = min(dp[i | (1<<(k-1))][k],dp[i][j]+mp[j][k]);

表示在状态i的时候,到达目的j的最短路最后扫一遍就可以了
代码:

#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<string>#include<set>#include<map>#include<queue>#include<stack>#include<cstring>using namespace std;#define LL long longvector<int>vec[100005];int in[100005];priority_queue<int>que;int ans[100005];int main(){    int n;    while(scanf("%d",&n) && n!=0)    {        int mp[15][15];        n++;        for(int i = 0;i<n;i++)        {            for(int j = 0;j<n;j++)            {                scanf("%d",&mp[i][j]);            }        }        for(int k = 0;k<n;k++)        {            for(int i = 0;i<n;i++)            {                if(i==k)continue;                for(int j = 0;j<n;j++)                {                    if(i==j)continue;                    if(mp[i][j]>mp[i][k] + mp[k][j])                    {                        mp[i][j] = mp[i][k] + mp[k][j];                    }                }            }        }        int dp[1<<11][15];        memset(dp,0x3f,sizeof(dp));        for(int i = 1;i<n;i++)        {            dp[1<<(i-1)][i] = mp[0][i];        }        for(int i = 1;i<(1<<(n-1));i++)        {            for(int j = 1;j<n;j++)            {                if(!(i & (1<<(j-1))))continue;                for(int k = 1;k<n;k++)                {                    dp[i | (1<<(k-1))][k] = min(dp[i | (1<<(k-1))][k],dp[i][j]+mp[j][k]);                }            }        }        int ans = 999999999;        int all = (1<<(n-1))-1;        for(int i = 1;i<n;i++)        {            ans = min(ans,dp[all][i]+mp[i][0]); // 从最短地方返回原点        }        printf("%d\n",ans);    }    return 0;}
阅读全文
0 0