• Jzoj4841 平衡的子集


    夏令营有N个人,每个人的力气为M(i)。请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法?

    这道题我们拷打数据范围后知道应该是折半搜索了

    但是似乎不是那么好做

    我们考虑如何搜索,显然每个人有三种状态,在队伍1中,在队伍2中和没有被选入

    我们将所有可能的状态都搜索出来加入一个数据结构(按照队伍1-队伍2的力量之差p作为关键字)

    但是这样做是有问题的,很多情况下会重复计算

    例如,四个人M为1 1 1 1,折半搜索以后,我们会得到以下几个状态{-2,-1,0,1,2},其中有两种可能的情况

    1.两种状态所选人物完全相同但因为分配方法不同导致p不相同

    2.两种状态所选人物不同但是因为分配方法导致p相同

    所以我们不能简单记录选了哪些人或者是这些人的p是多少而是两者都要计算

    所以我们可以考虑用map套set(一个p和一个k对应了一种选人的方法)

    map的第一维表示的是p,每个节点都是一个set存储一个二进制的选人方案k(1表示选择,0表示不选)

    这样的话在第二次搜索时,我们将值为-p的那个set拿出来,遍历其中每一个节点,在全局开一个数组vs表示某种选人的方式是否合法

    最后统计答案即可

    注:本题正解应为hash表

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<set> 
    #include<map>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    map<int,set<int> > s; 
    set<int> vis[1024],q; 
    int n,v[30],m,ans=0;
    bool vs[1<<20]; 
    void dfs(int x,int p,int k){
    	if(x>m) s[p].insert(k); 
    	else {
    		dfs(x+1,p,k);//x不选
    		dfs(x+1,p+v[x],k+(1<<x-1));//x加入队伍1
    		dfs(x+1,p-v[x],k+(1<<x-1));//x加入队伍2
    	}
    }
    void dgs(int x,int p,int k){
    	if(x>n){
    		if(!vis[k].count(p)&&s.count(-p)){ //判重,对于k和p相等的情况可以不用重复计算
    			q=s[-p];
    			for(set<int>::iterator it=q.begin();it!=q.end();++it) vs[*it+(k<<10)]=1;  //遍历set统计答案
    			vis[k].insert(p);
    			return;
    		}
    		return;
    	} else {
    		dgs(x+1,p,k);
    		dgs(x+1,p+v[x],k+(1<<x-m-1));
    		dgs(x+1,p-v[x],k+(1<<x-m-1));
    	}
    }
    int main(){
    	freopen("subset.in","r",stdin);
    	freopen("subset.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",v+i);
    	m=n>>1;
    	dfs(1,0,0); 
    	dgs(m+1,0,0);
    	for(int i=1;i<(1<<20);++i) ans+=vs[i];
    	printf("%d
    ",ans);
    }

  • 相关阅读:
    hadoop学习笔记(一):hadoop集群搭建
    CITA 快速入门
    Oracle数据库常用十一大操作指令
    Shutdown Abort :亚马逊成功迁移物流业务中最后一个Oracle数据库
    从B站源码泄露事件入手,说一下团队协作中版本管理的安全意识
    Docker三剑客:Compose、Machine和Swarm
    TensorFlow学习笔记之图像大小调整(最全可运行的代码)
    面试Python工程师,这几道编码题有必要背背,Python面试题No8
    WFP之位图效果
    使用ScriptX控件进行Web横向打印
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/7774323.html
Copyright © 2020-2023  润新知