bzoj2679 [Usaco2012 Open]Balanced Cow Subsets折半搜索

来源:互联网 发布:虎扑认证淘宝店铺 编辑:程序博客网 时间:2024/06/06 01:15

每个数可以选,不选。
不选可以分成被选到另外一个集合或者不被任何集合选择。
对应系数是1 0 -1。。
那么分成两半搜索,然后用双指针统计答案。
具体见code 现在才知道折半搜索就是meet in the middle

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;int n,m;const int N=1e5+5;int vis[N*20];int a[N],ans,cnt1,cnt2;struct node{    int now,s;}b[N],c[N];bool cmp1(node a,node b){    return a.s<b.s;}bool cmp2(node a,node b){    return a.s>b.s;}inline void dfs(int x,int y,int sum,int now){    if (x>y)    {        if (y==n/2)        {            b[++cnt1].s=sum;            b[cnt1].now=now;        }        else         {            c[++cnt2].s=sum;            c[cnt2].now=now;        }        return;    }    dfs(x+1,y,sum,now);    dfs(x+1,y,sum-a[x],now+(1<<(x-1)));    dfs(x+1,y,sum+a[x],now+(1<<(x-1)));}int main(){    scanf("%d",&n);    fo(i,1,n)scanf("%d",&a[i]);    dfs(1,n/2,0,0);    dfs(n/2+1,n,0,0);    sort(b+1,b+1+cnt1,cmp1);    sort(c+1,c+1+cnt2,cmp2);    int i=1,j=1;    ans=0;    while (i<=cnt1&&j<=cnt2)    {        while (c[j].s>-b[i].s&&j<=cnt2)j++;        int k=j;        while(j<=cnt2&&c[j].s==-b[i].s)        {            if (!vis[b[i].now|c[j].now])            {                vis[b[i].now|c[j].now]=1;                ans++;            }            j++;        }        if (b[i].s==b[i+1].s&&i<cnt1)j=k;        i++;    }    printf("%d\n",ans-1);    return 0;}
0 0
原创粉丝点击