2679: [Usaco2012 Open]Balanced Cow Subsets
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 316 Solved: 128
[Submit][Status][Discuss]
Description
Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk each day (1 <= M(i) <= 100,000,000). FJ wants to streamline the process of milking his cows every day, so he installs a brand new milking machine in his barn. Unfortunately, the machine turns out to be far too sensitive: it only works properly if the cows on the left side of the barn have the exact same total milk output as the cows on the right side of the barn! Let us call a subset of cows "balanced" if it can be partitioned into two groups having equal milk output. Since only a balanced subset of cows can make the milking machine work, FJ wonders how many subsets of his N cows are balanced. Please help him compute this quantity.
给出N(1≤N≤20)个数M(i) (1 <= M(i) <= 100,000,000),在其中选若干个数,如果这几个数可以分成两个和相等的集合,那么方案数加1。问总方案数。
Input
Line 1: The integer N.
Lines 2..1+N: Line i+1 contains M(i).
Output
* Line 1: The number of balanced subsets of cows.
Sample Input
4 1 2 3 4
INPUT DETAILS: There are 4 cows, with milk outputs 1, 2, 3, and 4.
INPUT DETAILS: There are 4 cows, with milk outputs 1, 2, 3, and 4.
Sample Output
3
OUTPUT DETAILS: There are three balanced subsets: the subset {1,2,3}, which can be partitioned into {1,2} and {3}, the subset {1,3,4}, which can be partitioned into {1,3} and {4}, and the subset {1,2,3,4} which can be partitioned into {1,4} and {2,3}.
OUTPUT DETAILS: There are three balanced subsets: the subset {1,2,3}, which can be partitioned into {1,2} and {3}, the subset {1,3,4}, which can be partitioned into {1,3} and {4}, and the subset {1,2,3,4} which can be partitioned into {1,4} and {2,3}.
第一次写折半搜索
就是meet in the middle
每个数的系数只能是-1,0,1,因此可以先通过 O(3n2) 的搜索分别搜索出两边每个状态的和以及数字的选择情况。
然后将后一半的状态按照和排序
O(2n2) 枚举前一半的每一个选择情况的状态,将该选择情况下所有状态按和排序,然后通过双指针求出所有合法状态。
时间复杂度去看zgz233的博客
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef double db;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline void print(int x)
{if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=50,M=4100000;
struct node{int sum,st;}x[M],y[M];
inline bool cmp1(const node &a,const node &b)
{return a.sum<b.sum;}
inline bool cmp2(const node &a,const node &b)
{return a.sum>b.sum;}
int cntx,cnty;
int a[N],n;
void dfs(int now,int aim,int sum,int st)
{
if(now>aim)
{
if(aim==n>>1)
{
x[++cntx].sum=sum;
x[cntx].st=st;
}
else
{
y[++cnty].sum=sum;
y[cnty].st=st;
}
return ;
}
dfs(now+1,aim,sum,st);
dfs(now+1,aim,sum+a[now],st+(1<<now));
dfs(now+1,aim,sum-a[now],st+(1<<now));
}
bool vis[M];
int main()
{
n=read();
register int i,j,ans;
for(i=1;i<=n;++i)a[i]=read();
dfs(1,n>>1,0,0);dfs((n>>1)+1,n,0,0);
sort(x+1,x+cntx+1,cmp1);sort(y+1,y+cnty+1,cmp2);
i=j=1,ans=0;
while(i<=cntx&&j<=cnty)
{
while(j<=cnty&&y[j].sum>-x[i].sum)++j;
int tmp=j;
while(y[j].sum+x[i].sum==0)
{
if(!vis[x[i].st|y[j].st])
{
ans++;
vis[x[i].st|y[j].st]=1;
}
j++;
}
j=tmp;
i++;
}
print(ans-1);puts("");return 0;
}
/*
4
1 2 3 4
3
*/