zoukankan      html  css  js  c++  java
  • COJ 1129 送货到家 (状态压缩DP)

    模型:求n个城市的最短hamilton回路,n<=15。

    分析:看到n<=15这样的条件容易想到状态压缩DP。hamilton回路其实就是n个城市的一个圆排列,任选一个起点最后的结果都一样,我们不妨设结点0为起点,状态设计也就不难了。

    状态设计:d[s][last],表示从结点0出发,已经走过的结点构成状态s,最后走的结点为last;

    状态转移:d[s][last]=MIN(d[ns][k]+g[k][last]),ns为s中去掉last那一位,k为ns中是1的位(不能是起点0);

    边界:当s中只有2位是1的时候,说明从0结点出发,到达last,所以直接返回g[0][last]。

    结果:ans=MIN(d[(1<<n)-1][k]+g[0][k]),k=1,2……n-1

    说明:这题坑爹的是NoAnswer的情况,题目没说明白,其实邻接矩阵中的0代表INF,说明不连通,就因为这个原因WA到吐血,最后问A了的人才明白。

    View Code
    #include <stdio.h>
    #include <string.h>
    #define N 16
    #define INF 0x3f3f3f3f
    #define MIN(a,b) ((a)<(b)?(a):(b))
    int n;
    int g[N][N];
    int dp[1<<N][N];
    int DP(int s,int last)
    {
        if(dp[s][last]!=-1) return dp[s][last];
    
        int ns=s^(1<<last);
        if(ns==1)    return  dp[s][last]=g[0][last];
    
        int ret=INF;
        for(int i=1;i<n;i++)
        {
            if((ns^(1<<i))<ns)  ret=MIN(ret,DP(ns,i)+g[i][last]);
        }
        return dp[s][last]=ret;
    }
    int main()
    {
        int i,j;
        while(~scanf("%d",&n))
        {
            for(i=0;i<n;i++)
            {
                for(j=0;j<n;j++)
                {
                    scanf("%d",&g[i][j]);
                    if(g[i][j]==0 && i^j)   g[i][j]=INF;
                }
            }
            int ans=INF;
            memset(dp,0xff,sizeof(dp));
            for(i=n-1;i;i--)
            {
                ans=MIN(ans,DP((1<<n)-1,i)+g[0][i]);
            }
            if(n==1)    ans=0;
            if(n==2)    ans=2*g[0][1];
            if(ans<INF) printf("%d\n",ans);
            else    puts("NoAnswer");
        }
        return 0;
    }
  • 相关阅读:
    编译器内置宏实现调试信息输出
    走进C标准库(4)——"stdio.h"中的putc
    走进C标准库(5)——"stdio.h"中的其他部分函数
    走进C标准库(2)——"stdio.h"中的fopen函数
    [转]深度探索C语言函数可变长参数
    C语言I博客作业02
    C语言I博客作业02
    第一周c语音作业
    什么是模块化,模块化的好处又是什么?
    服务端渲染和客户端渲染
  • 原文地址:https://www.cnblogs.com/algorithms/p/2623622.html
Copyright © 2011-2022 走看看