【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)
[Usaco2012 Open]Balanced Cow Subsets
题目描述
给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\),在其中选若干个数,如果这几个数可以分成两个和相等的集合,那么方案数加\(1\)。
求有多少种选数的方案。
输入输出格式
输入格式:
* Line 1: The integer $ N$.
* Lines 2..1+N: Line i+1 contains \(M(i)\).
输出格式:
* Line 1: The number of balanced subsets of cows.
输入输出样例
输入样例#1:
4
1
2
3
4
输出样例#1:
3
题解
这道题算是一个折半搜索(meet in the middle)的好题
如果对折半搜索不太熟悉,可以先做一道较简单的题 [CEOI2015 Day2]世界冰球锦标赛
这道题有三种状态
- 不放入任何集合
- 放入左边集合
- 放入右边集合
在搜索时如何表示呢,我们可以0,1,-1来表示,代码如下:
dfs(dep+1,sum);
dfs(dep+1,sum+v[dep]);
dfs(dep+1,sum-v[dep]);
但是我们得到的答案可能会有重复,就是我们可能把一个数选入左集合或右集合,但是都加入了状态,所以我们需要判重。
如何去判重,状态压缩,压成2进制去判重。
所以搜索时还要去记录状态,用一个\(vis\)数组判重。
if(!vis[a[l].state|b[r].state])
vis[a[l].state|b[r].state]=1;//state记录二进制的选数状态 1表示选 0表示没选
最后要统计答案,排序后双指针扫描一遍即可。
注意,最后别忘了把0的那种方案减去。
code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cctype>
#define ll long long
#define R register
#define N 22
using namespace std;
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
a=f*x;
}
int n,v[N<<1],maxdep,cnta,cntb;
bool vis[1<<N];
ll ans;
struct node{
int state,x;
}a[1<<N],b[1<<N];
inline bool cmp1(R node a,R node b){
return a.x<b.x;
}
inline bool cmp2(R node a,R node b){
return a.x>b.x;
}
inline void dfs(R int dep,R int sum,R int now,R int flg){
if(dep==maxdep+1){
if(!flg){
a[++cnta].x=sum;
a[cnta].state=now;
}
else{
b[++cntb].x=sum;
b[cntb].state=now;
}
return;
}
dfs(dep+1,sum,now,flg);
dfs(dep+1,sum+v[dep],now+(1<<(dep-1)),flg);
dfs(dep+1,sum-v[dep],now+(1<<(dep-1)),flg);
}
int main(){
read(n);
for(R int i=1;i<=n;i++)read(v[i]);
maxdep=n/2;dfs(1,0,0,0);
maxdep=n;dfs(n/2+1,0,0,1);
sort(a+1,a+1+cnta,cmp1);
sort(b+1,b+1+cntb,cmp2);
R int l=1,r=1;
while(l<=cnta&&r<=cntb){
while(-a[l].x<b[r].x&&r<=cntb)r++;
R int pos=r;
while(r<=cntb&&-a[l].x==b[r].x){
if(!vis[a[l].state|b[r].state]){
vis[a[l].state|b[r].state]=1;
ans++;
}
r++;
}
if(l<cnta&&a[l].x==a[l+1].x)r=pos;
l++;
}
printf("%lld\n",ans-1);
return 0;
}
【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)的更多相关文章
- bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)
2679: [Usaco2012 Open]Balanced Cow Subsets Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 462 Solv ...
- 【BZOJ】2679: [Usaco2012 Open]Balanced Cow Subsets
[算法]折半搜索+数学计数 [题意]给定n个数(n<=20),定义一种方案为选择若干个数,这些数可以分成两个和相等的集合(不同划分方式算一种),求方案数(数字不同即方案不同). [题解] 考虑直 ...
- BZOJ_2679_[Usaco2012 Open]Balanced Cow Subsets _meet in middle+双指针
BZOJ_2679_[Usaco2012 Open]Balanced Cow Subsets _meet in middle+双指针 Description Farmer John's owns N ...
- 折半搜索+Hash表+状态压缩 | [Usaco2012 Open]Balanced Cow Subsets | BZOJ 2679 | Luogu SP11469
题面:SP11469 SUBSET - Balanced Cow Subsets 题解: 对于任意一个数,它要么属于集合A,要么属于集合B,要么不选它.对应以上三种情况设置三个系数1.-1.0,于是将 ...
- [Usaco2012 Open]Balanced Cow Subsets
Description Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk ...
- BZOJ2679 : [Usaco2012 Open]Balanced Cow Subsets
考虑折半搜索,每个数的系数只能是-1,0,1之中的一个,因此可以先通过$O(3^\frac{n}{2})$的搜索分别搜索出两边每个状态的和以及数字的选择情况. 然后将后一半的状态按照和排序,$O(2^ ...
- bzoj2679:[Usaco2012 Open]Balanced Cow Subsets
思路:折半搜索,每个数的状态只有三种:不选.选入集合A.选入集合B,然后就暴搜出其中一半,插入hash表,然后再暴搜另一半,在hash表里查找就好了. #include<iostream> ...
- SPOJ-SUBSET Balanced Cow Subsets
嘟嘟嘟spoj 嘟嘟嘟vjudge 嘟嘟嘟luogu 这个数据范围都能想到是折半搜索. 但具体怎么搜呢? 还得扣着方程模型来想:我们把题中的两个相等的集合分别叫做左边和右边,令序列前一半中放到左边的数 ...
- codeforces912E(折半搜索+双指针+二分答案)
E. Prime Gift E. Prime Gift time limit per test 3.5 seconds memory limit per test 256 megabytes inpu ...
随机推荐
- Cannot+use+T4+templates+inside+a+.NET+Core+project,NetCore2.0无法使用T4模板解决方法
Cannot+use+T4+templates+inside+a+.NET+Core+project,NetCore2.0无法使用T4模板解决方法 请见:https://csharp.wekeepco ...
- 由等概率生成的0和1构建rand()函数
问题:有函数rand01()能够等概率的生成0和1,用rand01生成rand(n),使其能够等概率的生成0-n-1的整数. java代码: public int rand(int n){ while ...
- 当一个SQL语句同时出现了where,group by,having,order by的时候,执行顺序和编写顺序
当一个查询语句同时出现了where,group by,having,order by的时候,执行顺序和编写顺序 1.执行where xx对全表数据做筛选,返回第1个结果集. 2.针对第1个结果集使用g ...
- Angular24 树形菜单 ???
待更新... 2018年5月21日15:17:47 参考博文01 参考博文02
- linux ssh使用深度解析(key登录详解)
linux ssh使用深度解析(key登录详解) SSH全称Secure SHell,顾名思义就是非常安全的shell的意思,SSH协议是IETF(Internet Engineering Task ...
- 命令行编译java的一点总结
今天在使用命令行编译时遇到些问题,顺便又仔细分析了一些基础知识,记录总结一下. 下面使用javac和java命令都是在 D:\Workspace\java目录下执行的: 1 //Inner.java ...
- ROS naviagtion analysis: costmap_2d--CostmapLayer
博客转自:https://blog.csdn.net/u013158492/article/details/50493220 这个类是为ObstacleLayer StaticLayer voxelL ...
- 几种导入osm(openstreetmap)数据的方法
一osm2pgsql+postgresql+postgis osm2pgsql——是由OpenStreetMap开发的一个命令行工具负责将OSM数据导入到基于PostgresSql的Postgis的 ...
- jqentitymanage
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflect ...
- poj1840 Eqs(hash+折半枚举)
Description Consider equations having the following form: a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 The co ...