• 环游世界


    环游世界

    有n个地方(标号1到n)要从标号为0的地方出去,经过所有的地方之后回来,求最短的时间,输入(n+1)*(n+1)的矩阵a,a[i][j]a[i][j]表示顶点ii到顶点jj所需要的时间。

    输入

    第一行输入一个整数n (1 le n le 10)n(1n10)。

    接下来n + 1n+1行,每行n + 1n+1个整数,表示矩阵中的元素,矩阵中的元素在区间[1, 1000][1,1000]内。

    输出

    输出最短时间。

    样例

    输入

    复制
    3
    0 1 10 10
    1 0 1 2
    10 1 0 10
    10 2 10 0

    输出

    复制
    8

    提示

    子任务1,30分,1 <= n <=9

    子任务2,70分,全范围。

    分析

    状态压缩DP模板。

    那么,什么是状压dp呢?

    简单来说,就是基于集合的dp。本题中状态转移取决于走过的点集和当前位置(最终答案由走完了所有点的状态再回到起点)。

    状压就在于记录走过的点集的状态,相当于用二进制表示。

    假设0表示该点没走过,1表示走过,对于一个四个点的情况,共有16种状态

    0000

    0001

    0010

    0011

    .......

    1111

    那么,对于n个点的情况,每个点都有选和不选两种情况,共有2^n种情况

    所以dp中记录点集状态的那一维开成1<<n

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    int dp[1<<14][14];
    int dis[14][14];
    void checkmin(int &x,int y)
    {
        if(x==-1||x>y)
            x=y;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF){
        
            if(!n) break;
                n++;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&dis[i][j]);
        for(int k=0;k<n;k++)
             for(int i=0;i<n;i++)
                 for(int j=0;j<n;j++)
                     if(dis[i][j]>dis[i][k]+dis[k][j])
                         dis[i][j]=dis[i][k]+dis[k][j];
        memset(dp,-1,sizeof(dp));
        dp[1][0]=0; 
        for(int mask=1;mask<(1<<n) ;mask++)
            for(int end=0;end<n;end++)
                if(dp[mask][end]!=-1)
                {
                    for(int nxt=0;nxt<n;nxt++)
                    {
                        if(! (mask&(1<<nxt)) )
                        {
                            checkmin(dp[mask|(1<<nxt)][nxt],dp[mask][end]+dis[end][nxt]);
                            
                        }
                    }
                }
        int ans=-1;
        for(int end=0;end<n;end++)
        {
            if(dp[(1<<n)-1][end]!=-1)//此处的特殊判断要注意!
            checkmin(ans,dp[(1<<n)-1][end]+dis[end][0]);
        }
        printf("%d",ans);
    }    
        return 0;
    }
  • 相关阅读:
    洛谷 P5057 [CQOI2006]简单题 题解
    洛谷 P3368 【模板】树状数组 2 题解
    洛谷 P3374 【模板】树状数组 1 题解
    洛谷 P2023 [AHOI2009]维护序列 题解
    洛谷 P2253 好一个一中腰鼓! 题解
    求最长不下降/上升/下降/不上升子序列
    [SQL Server]Index/deadlock
    Ubuntu 14.04下从源码安装qt4.x
    Ubuntu系统下Import cv2提示no modules ...错误
    Ubuntu 14.04下安装CUDA8.0
  • 原文地址:https://www.cnblogs.com/conprour/p/14728922.html
Copyright © 2020-2023  润新知