码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5823

时间:2017-02-15 00:33:41      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:alt   closed   ++   枚举   break   表示   using   mem   while   

官方题解:直接状压dp就行了,f[S]表示点集S的色数,枚举子集转移(子集是独立集)。这样是3^n的。

这样就可以过了……(独立集就是点互相没有连边)

学到了一个穷举子集的简便写法

for (int j=i; j; j=(j-1)&i)

技术分享
 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 int f[300010],q[20],n,t;
 5 bool v[300010];
 6 char a[20][20];
 7 unsigned int d[300010];
 8 
 9 void dfs(int i,int st,bool ff)
10 {
11     if (i==n) v[st]=ff;
12     else {
13         dfs(i+1,st,ff);
14         if (ff)
15         {
16             for (int j=1; j<=t; j++)
17                 if (a[q[j]][i]==1) {ff=0;break;}
18         }
19         q[++t]=i;
20         dfs(i+1,st|(1<<i),ff);
21         t--;
22     }
23 }
24 
25 int main()
26 {
27     int cas;
28     scanf("%d",&cas);
29     d[0]=1;
30     for (int i=1; i<(1<<18); i++) d[i]=d[i-1]*233;
31     while (cas--)
32     {
33         scanf("%d",&n);
34         for (int i=0; i<n; i++)
35             scanf("%s",a[i]);
36         int m=1<<n;t=0;
37         memset(v,0,sizeof(v));
38         dfs(0,0,1);
39         for (int i=1; i<m; i++) f[i]=n;
40         f[0]=0;
41         for (int i=1; i<m; i++)
42             for (int j=i; j; j=(j-1)&i)
43                 if (v[j]) f[i]=min(f[i],f[i-j]+1);
44         unsigned int ans=0;
45         for (int i=1; i<m; i++) ans+=d[i]*f[i];
46         printf("%u\n",ans);
47     }
48 }
View Code

 

hdu5823

标签:alt   closed   ++   枚举   break   表示   using   mem   while   

原文地址:http://www.cnblogs.com/phile/p/6399484.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!