• POJ 3311 Hie with the Pie floyd+状压DP


    链接: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 15
    typedef 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
    ",ans);
        }
        return 0;
    }


  • 相关阅读:
    最新版 VS2015|Visual Studio Enterprise 2015简体中文版(企业版)
    MY97 日期控件只输入今天之前的值
    VARIANT类型
    C++ Struct
    MFC网络编程
    套接字编程(VC_Win32)
    套接字相关函数
    网络编程
    char str[] 与 char *str的区别详细解析
    Windows下C++多线程同步与互斥简单运用
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4293987.html
Copyright © 2020-2023  润新知