bzoj_2064 分裂
可能是一个思维题,首先是状压
将大陆分成两部分,一部分是原来的,一部分是最后的
将最后的大陆面积取负数
sum(i)表示i这个状态的总和,sum(i)==0表明他们的和相等
然后如果直接暴力和起来,再暴力分开,那么总的是n+m-2
发现一个规律不,两个集合中和相等的子集个数*2,是n+m要减的
那么可以状压做
具体看代码,只可意会不可言传
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define dd double #define lob(x) (x&(-(x))) using namespace std; inline void read(int &a) { a=0; char q=getchar(); while(q<'0'||q>'9') q=getchar(); while(q>='0'&&q<='9') a=a*10+q-'0',q=getchar(); } bool cmp(int a,int b) { return a>b; } int n1,n2; int v1[13],v2[13]; int bit[23]; int sum[(1<<20)+5],f[(1<<20)+5]; int main(){ bit[1]=1; for(int i=2;i<=23;++i) bit[i]=bit[i-1]<<1; read(n1); int tin; for(int i=1;i<=n1;++i) read(tin),sum[bit[i]]=tin; read(n2); for(int i=1;i<=n2;++i) read(tin),sum[bit[i+n1]]=-tin; int maxp=bit[n1+n2+1]-1,ss=n1+n2; for(int i=1;i<=maxp;++i) { sum[i]=sum[i-lob(i)]+sum[lob(i)]; for(int j=1;j<=ss;++j) if(i&bit[j]) f[i]=max(f[i],f[i-bit[j]]); if(sum[i]==0) ++f[i]; } cout<<(ss-2*f[maxp]); }