hdu5823

官方题解:直接状压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
",ans);
47     }
48 }
View Code
原文地址:https://www.cnblogs.com/phile/p/6399484.html