hdu 5823 color II——子集dp(独立集)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5823
独立集染一种颜色。在这个基础上枚举子集来dp。
状压一样地存边真是美妙。
2^32是1ll<<32,不是1<<31。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=25,Lm=(1<<18)+5; const ll mod=(1ll<<32); int T,n,lm,b[N],dp[Lm]; ll ans,sum; bool inv[Lm],flag; int calc(int s){int ret=0;while(s)ret++,s-=(s&-s);return ret;} int main() { scanf("%d",&T); while(T--) { memset(b,0,sizeof b); scanf("%d",&n);int x; lm=(1<<n); for(int i=1;i<=n;i++) for(int j=0;j<n;j++) { scanf("%1d",&x); if(x)b[i]|=(1<<j); } for(int s=1;s<lm;s++) { flag=1; for(int i=1;i<=n;i++) if((s&(1<<(i-1)))&&(s&b[i])) {flag=0;break;} inv[s]=flag; } ans=0;sum=1; for(int s=1;s<lm;s++) { sum=sum*233%mod; dp[s]=calc(s); for(int d=s;d;d=((d-1)&s))//从s开始,为了:自己就是独立集 if(inv[d])dp[s]=min(dp[s],dp[s^d]+1); ans=(ans+dp[s]*sum)%mod; } printf("%lld\n",ans); } return 0; }