zoukankan      html  css  js  c++  java
  • [Usaco2012 Open]Balanced Cow Subsets

    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

    Sample Output
    3


    直接搜复杂度(O(3^n)),显然不行,考虑折半搜索,分成两部分,这样复杂度变为(O(2*3^{n/2})),然后对两部分进行查找即可,细节见代码

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=20,M=6e4;
    struct S1{
    	int val,sta;
    	void insert(int v,int s){val=v,sta=s;}
    }A[M+10],B[M+10];
    int v[N+10],cntA,cntB,n;
    bool vis[(1<<N)+10];
    bool cmp1(const S1 &x,const S1 &y){return x.val<y.val;}
    bool cmp2(const S1 &x,const S1 &y){return x.val>y.val;}
    void dfs(int x,int limit,int sta,int sum){
    	if (x>limit){
    		limit==n>>1?A[++cntA].insert(sum,sta):B[++cntB].insert(sum,sta);
    		return;
    	}
    	dfs(x+1,limit,sta,sum);
    	dfs(x+1,limit,sta|(1<<(x-1)),sum+v[x]);
    	dfs(x+1,limit,sta|(1<<(x-1)),sum-v[x]);
    }
    int main(){
    	n=read();
    	for (int i=1;i<=n;i++)	v[i]=read();
    	dfs(1,n>>1,0,0),dfs((n>>1)+1,n,0,0);
    	sort(A+1,A+1+cntA,cmp1);
    	sort(B+1,B+1+cntB,cmp2);
    	int i=1,j=1,Ans=0;
    	while (i<=cntA&&j<=cntB){
    		while (j<=cntB&&-B[j].val<A[i].val)	j++;
    		int tmp=j;
    		while (A[i].val+B[j].val==0){
    			if (!vis[A[i].sta|B[j].sta])	vis[A[i].sta|B[j].sta]=1,Ans++;
    			j++;
    		}
    		j=tmp,i++;
    	}
    	printf("%d
    ",Ans-1);
    }
    
  • 相关阅读:
    POJ 3070 Fibonacci【矩阵连乘】
    hdu 3038 How Many Answers Are Wrong【并查集的简单应用】
    POJ 2236 Wireless Network 【并查集的简单应用 判断是否在同一连通分量】
    POJ 1984 Navigation Nightmare【并查集思路总结】
    POJ 2492 A Bug's Life【并查集的简单应用同类的判断】
    POJ 1703 Find them, Catch them【典型并查集:判断在不同的集合】
    POJ 1456 Supermarket【贪心 + 并查集】
    ZOJ 3261 Connections in Galaxy War【并查集】
    POJ 1984 Navigation Nightmare
    POJ 1988 Cube Stacking【并查集的简单应用 堆木块】
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10020897.html
Copyright © 2011-2022 走看看