zoukankan      html  css  js  c++  java
  • USACO 2012 OPEN GOLD subsets(Meet-In-The-Middle)

    Problem

    有多少个非空子集,能划分成和相等的两份。

    Solution

    直接对于这n个数分成左右两个部分,然后考虑每一个数:

    1. 在第一个集合
    2. 在第二个集合
    3. 两个集合都不在

    所以可以直接对于这个东西搞一个Map和一个Set存一下,考虑把左边的和和右边的和分别抠出来,然后搞一下就可以了。

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<set>
    #include<map>
    #define ll long long
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    using namespace std;
    inline int gi(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    inline ll gl(){
    	ll sum=0,f=1;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    int dp[2000010],m[30],n,f[2000010],ans,vis[30],cnt;
    map<int,int>M;
    set<int>S[2000010];
    void dfs1(int i,int s,int d){
    	if(i==n/2){
    		if(M.find(d)==M.end())M[d]=++cnt;
    		int t=M[d];
    		S[t].insert(s);
    		return;
    	}
    	dfs1(i+1,s,d);
    	dfs1(i+1,s|(1<<i),d+m[i]);
    	dfs1(i+1,s|(1<<i),d-m[i]);
    }
    void dfs2(int i,int s,int d){
    	if(i>n-1){
    		if(M.find(d)==M.end())return;
    		int t=M[d];
    		set<int>::iterator it;
    		for(it=S[t].begin();it!=S[t].end();it++)
    			dp[(*it)|s]=1;
    		return;
    	}
    	dfs2(i+1,s,d);
    	dfs2(i+1,s|(1<<i),d+m[i]);
    	dfs2(i+1,s|(1<<i),d-m[i]);
    }
    int main(){
    	file("subsets");
            int i,j,k;
    	n=gi();
    	for(i=0;i<n;i++)m[i]=gi();
    	dfs1(0,0,0);
    	dfs2(n/2,0,0);
    	for(i=1;i<1<<n;i++)ans+=dp[i];
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    素数路径Prime Path POJ3126 素数,BFS
    Fliptile POJ3279 DFS
    Find the Multiple POJ1426
    洗牌Shuffle'm Up POJ3087 模拟
    棋盘问题 POJ1321 DFS
    抓住那只牛!Catch That Cow POJ3278 BFS
    Dungeon Master POJ2251 三维BFS
    Splitting into digits CodeForce#1104A
    Ubuntu下手动安装Nvidia显卡驱动
    最大连续子序列和
  • 原文地址:https://www.cnblogs.com/cjgjh/p/9798029.html
Copyright © 2011-2022 走看看