zoukankan      html  css  js  c++  java
  • HDU 5823 (状压dp)

    Problem color II

    题目大意

      定义一个无向图的价值为给每个节点染色使得每条边连接的两个节点颜色不同的最少颜色数。

      对于给定的一张由n个点组成的无向图,求该图的2^n-1张非空子图的价值。

      n <= 18

    解题分析

      官方题解:

        直接状压dp就行了,f[S]表示点集S的色数,枚举子集转移(子集是独立集)。这样是3^n的。 一个复杂度更优的做法是把所有独立集都预处理出来,然后作n次or卷积。这样是n^2*2^n的。

      

      枚举子集的子集的时间复杂度是3^n 啊 。 即 sigma( C(n,k) * 2 ^k ) = (1 + 2 ) ^ n = 3 ^ n 。

    参考程序

     1 #include <map>
     2 #include <set>
     3 #include <stack>
     4 #include <queue>
     5 #include <cmath>
     6 #include <ctime>
     7 #include <string>
     8 #include <vector>
     9 #include <cstdio>
    10 #include <cstdlib>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <cassert>
    15 #pragma comment(linker,"/STACK:102400000,102400000")
    16 using namespace std;
    17 
    18 #define     N             100008             
    19 #define     V             1008
    20 #define        E            60008    
    21 #define        lson        l,m,rt<<1
    22 #define     rson        m,r+1,rt<<1|1
    23 #define        clr(x,v)    memset(x,v,sizeof(x));
    24 #define        LL            long long 
    25 
    26 const int    mo    =    1000000007;
    27 const int     inf =    0x3f3f3f3f;
    28 const int     INF =    2000000000;
    29 /**************************************************************************/ 
    30 
    31 int n;
    32 char s[20][20];
    33 int id[1<<20];
    34 unsigned dp[1<<20];
    35 
    36 void work(){
    37 
    38     scanf("%d",&n);
    39     for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
    40     int lx=1<<n;
    41     for (int i=0;i<lx;i++) id[i]=1;
    42     for (int i=1;i<lx;i++){
    43         int u,v;
    44         for (u=n;u>=1;u--) if (i & 1<<u-1) break;
    45         if (!id[i- (1 << u-1)]) id[i]=0;
    46         for (v=1;v<=n;v++) 
    47             if (i & 1 << v-1 && u!=v && s[u][v]=='1')
    48                 id[i]=0;
    49     }
    50     for (int i=0;i<lx;i++) dp[i]=20;
    51     dp[0]=0;
    52     for (int i=1;i<lx;i++)
    53         for (int j=i;j;j=(j-1) & i) if (id[j])  //  枚举 子集的子集  黑科技好强啊 !!
    54         {
    55             dp[i]=min(dp[i],dp[i-j]+1);
    56         }        
    57     unsigned res=0,tmp=1;
    58     for (int i=1;i<lx;i++){
    59         tmp = tmp * 233;
    60         res = res + tmp * dp[i];
    61     }
    62     printf("%u
    ",res);
    63 }
    64 
    65 int main(){
    66     int T;
    67     scanf("%d",&T);
    68     while (T--) work();
    69 }
    View Code
  • 相关阅读:
    【09-04】java内部类学习笔记
    【09-03】java泛型学习笔记
    【08-23】redis学习笔记
    【06-23】js动画学习笔记01
    【11-23】mysql学习笔记02
    【06-18】CentOS使用笔记
    thinkphp+datatables+ajax 大量数据服务器端查询
    python遗传算法实现数据拟合
    简单的新闻客户端APP开发(DCloud+thinkphp+scrapy)
    python游戏编程——跟13岁儿童学编程
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5762546.html
Copyright © 2011-2022 走看看