bzoj_2064 分裂

可能是一个思维题,首先是状压

将大陆分成两部分,一部分是原来的,一部分是最后的

将最后的大陆面积取负数

sum(i)表示i这个状态的总和,sum(i)==0表明他们的和相等

然后如果直接暴力和起来,再暴力分开,那么总的是n+m-2

发现一个规律不,两个集合中和相等的子集个数*2,是n+m要减的

那么可以状压做

具体看代码,只可意会不可言传

 

#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]);
}
AA

 

posted @ 2017-10-20 18:35  A_LEAF  阅读(125)  评论(0编辑  收藏  举报