• 暑假集训每日一题0720(状态压缩DP)


    Description

     有N个点,有一个商人想经过所有的点恰好一次(商人最终不一定要回到起点),求商人需要走最短路程。

    Input

     两个整数N,M表示图的点数和边数,接下去有M行,每行三个整数a ,b ,c 表示从a到b有一条无向边,长度是c

    N<=15  c<=10000 

    Output

     输出商人需要走过的最短距离 ,如果不能到达所有的点,输出-1 。

    Sample Input

    4 6
    1 2 1
    1 4 2
    4 3 4
    2 3 3
    2 4 6
    1 3 5

    Sample Output

    6
     
    将已走过的点和未走过的点用二进制编码成整数,然后再DP.
    例如:共4个点,1和2已走过,3和4未走,此时状态编码为二进制0011,对应整数为3。
    状态设计为c[end][state]表示为当前状态为state,且最后访问的结点为end。
    状态转移为:c[end][state]=MIN(c[i][s]+dist[i][end]),i为state的二进制中是1的位置,s为将state中的第end位变0后的整数。
    边界条件为:state的二进制表示中只有1位为1,其余全为0,此时表示刚出发的状态,返回0。
    需要注意的是在用位运算的时候一定要记得加括号,否则因为优先级的问题会出现一些不可预知的错误,例如RE。
    View Code
    #include <stdio.h>
    #include <string.h>
    #define MIN(a,b) ((a)<(b)?(a):(b))
    #define N 15
    #define INF 10000001
    int n,m;
    int d[N][N],c[N][1<<15];
    int dp(int end,int state)
    {
        int i,j,s,ans;
        if(c[end][state]!=-1)   return c[end][state];
        if((state&(state-1))==0)  return c[end][state]=0;
        s=state^(1<<end);
        ans=INF;
        for(i=0;i<n;i++)
        {
            if((s|(1<<i))==s)  ans=MIN(ans,dp(i,s)+d[i][end]);
        }
        return c[end][state]=ans;
    }
    int main()
    {
        int i,j,ans;
        while(~scanf("%d%d",&n,&m))
        {
            for(i=0;i<n;i++)
            {
                for(j=0;j<i;j++)    d[i][j]=d[j][i]=INF;
                memset(c[i],-1,sizeof(int)*(1<<n));
            }
            while(m--)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                a--,b--;
                d[a][b]=d[b][a]=MIN(d[a][b],c);
            }
            ans=INF;
            for(i=0;i<n;i++)    ans=MIN(ans,dp(i,(1<<n)-1));
            if(ans<INF) printf("%d\n",ans);
            else    puts("-1");
        }
        return 0;
    }
  • 相关阅读:
    手写web框架之加载配置项目
    JAVA中注解的实现原理
    使用Mock 测试 controller层
    如何写resultful接口
    RSA加密、解密、签名、验签的原理及方法
    AES256位加密
    聊聊分布式事务,再说说解决方案
    分布式锁简单入门以及三种实现方式介绍
    redis总结(面试中容易遇到的)
    字符串匹配的KMP算法
  • 原文地址:https://www.cnblogs.com/algorithms/p/2601382.html
Copyright © 2020-2023  润新知