您的位置:首页 > 运维架构

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

2017-04-24 21:04 429 查看
每个数可以选,不选。

不选可以分成被选到另外一个集合或者不被任何集合选择。

对应系数是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
,ans,cnt1,cnt2;
struct node
{
int now,s;
}b
,c
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: