标签: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 }
标签:alt closed ++ 枚举 break 表示 using mem while
原文地址:http://www.cnblogs.com/phile/p/6399484.html