zoukankan      html  css  js  c++  java
  • POJ 3311 Hie with the Pie(Floyd+状态压缩DP)

    题是看了这位的博客之后理解的,只不过我是又加了点简单的注释。

    链接:http://blog.csdn.net/chinaczy/article/details/5890768

    我还加了一些注释代码,对于新手的我,看起来可能更方便些吧,顺便说下快捷键

    先选中要操作的行,ctrl+shift+c 是注释 ctrl+shift+x是解注释(cb的快捷键)

    /*
    Floyd + 状态压缩DP
    题意是有N个城市(1~N)和一个PIZZA店(0),要求一条回路,从0出发,又回到0,而且距离最短
    也就是TSP(旅行商)问题,首先不难想到用FLOYD先求出任意2点的距离dis[i][j]
    接着枚举所有状态,用11位二进制表示10个城市和pizza店,1表示经过,0表示没有经过
    定义状态DP(S,i)表示在S状态下,到达城市I的最优值
    接着状态转移方程:DP(S,i) = min{DP(S^(1<<i-1),k) + dis[k][j],DP(S,i)},其中S^(1<<i-1)表示未到达城市i的所有状态,1<=k<=n
    对于全1的状态,即S = (1<<n)-1则表示经过所有城市的状态,最终还需要回到PIZZA店0
    那么最终答案就是min{DP(S,i) + dis[i][0]}
    
    TSP是NP困难问题,所以地图必须要小,本题是10,所以也可以根据这个想到floyd,(时间复杂度n^3)和状压dp (用二进制存10位,且只有2个状态,走过,没走过)
    */
    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define INF 100000000
    using namespace std;
    int dis[12][12];
    int dp[1<<11][12];
    int n,ans,_min;
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("C:\Users\Zmy\Desktop\in.txt","r",stdin);//这应该修改下重定向的文件路径
    //    freopen("C:\Users\Zmy\Desktop\out.txt","w",stdout);
    #endif // ONLINE_JUDGE
        while(scanf("%d",&n) && n)
        {
            /**< 输入 */
            for(int i = 0; i <= n; ++i)
                for(int j = 0; j <= n; ++j)
                    scanf("%d",&dis[i][j]);
    
    //        puts("before");
    //        for(int i = 0; i <= n; ++i)
    //        {
    //            for(int j = 0; j <= n; ++j)
    //                printf("%3d ",dis[i][j]);
    //            puts("");
    //        }
    
            /**< 这段用弗洛伊德求出了从i点到各个j点的最短距离 存在了dis中,即更新了dis */
            for(int k = 0; k <= n; ++k)
                for(int i = 0; i <= n; ++i)
                    for(int j = 0; j <= n; ++j)
                        if(dis[i][k] + dis[k][j] < dis[i][j])
                            dis[i][j] = dis[i][k] + dis[k][j];
    
    //        puts("after");
    //        for(int i = 0; i <= n; ++i)
    //        {
    //            for(int j = 0; j <= n; ++j)
    //                printf("%3d ",dis[i][j]);
    //            puts("");
    //        }
    
    
    
            for(int S = 0; S < (1<<n); ++S) //枚举所有状态,用位运算表示
                for(int i = 1; i <= n; ++i)
                {
                    if(S & (1<<(i-1)))//状态S中已经过城市i
                    {
    
                        /**< 注意:DP的边界是这句话,好牛逼!! */
                        if(S == (1<<(i-1)))	dp[S][i] = dis[0][i];//状态S只经过城市I,最优解自然是从0出发到i的dis,这也是DP的边界
    
                        //如果S有经过多个城市
                        else
                        {
                            dp[S][i] = INF;
    
                            //枚举不是城市I的其他城市
                            for(int j = 1; j <= n; ++j)
                            {
                                //在没经过城市I的状态中,寻找合适的中间点J使得距离更短,和FLOYD一样
                                if(S & (1<<(j-1)) && j != i)
                                    dp[S][i] = min(dp[S^(1<<(i-1))][j] + dis[j][i],dp[S][i]);
                            }
    
    
                        }
                    }
                }
            ans = dp[(1<<n)-1][1] + dis[1][0];
            for(int i = 2; i <= n; ++i)
                if(dp[(1<<n)-1][i] + dis[i][0] < ans)
                    ans = dp[(1<<n)-1][i] + dis[i][0];
            printf("%d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    Nuget常用命令(转)
    Core使用SAP Web Service
    jquery.dataTables动态列--转
    jqGrid随窗口大小变化自适应大小-转
    30个值得推荐的数据可视化工具--转
    Automapper问题记录
    MVC及MVC Core在filter中如何获取控制器名称和Action名称
    .Net Core使用 MiniProfiler 进行性能分析(转)
    Core中使用Hangfire
    ASP.NET 多环境下配置文件web.config的灵活配置---转
  • 原文地址:https://www.cnblogs.com/s1124yy/p/5520987.html
Copyright © 2011-2022 走看看