【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 ...
随机推荐
- Winform Datagridview 单元格html格式化支持富文本
Winform Datagridview 单元格html格式化支持富文本 示例: 源码:https://github.com/OceanAirdrop/DataGridViewHTMLCell 参考: ...
- 在线HTTP POST/GET接口测试工具
在线HTTP POST/GET接口测试工具 http://www.atool.org/httptest.php
- Centos手动编译安装vim8
系统:CentOs6.9 gcc版本:5.1.0 github上拉取vim工程之后,cd src,执行一下命令: $ ./configure $ sudo make gcc -c -I. -Iprot ...
- 201671010127 2016—2017-2 通过一个小程序对Java的再认识。
学习了将近四周的Java语言,对于Java语言,我也有了更进一步的理解,出于对Java语言的喜爱,我总是喜欢没事的时候,自己敲一些很简单的代码,一边学习Java语言,一边对比C语言,往往可以帮助我们更 ...
- 项目引入Solr时应该考虑的一些问题
1.数据更新频率:每天数据增量有多大,随时更新还是定时更新 2.数据总量:数据要保存多长时间 3.一致性要求:期望多长时间内看到更新的数据,最长允许多长时间延迟 4.数据特点:数据源包括哪些,平均单条 ...
- Rails 和 Django 的深度技术对比
我想以一个免责声明来开始下面的内容.我使用 Django开发网站已经有三年了,众所周知,我喜欢Django.我已经写了一个开源的应用程序( app),并且我已经将补丁发送到了Django.然而,我以尽 ...
- mysql sandbox的问题备忘
工具很好用,但是安装运行时有些小问题: 1.启动数据库时提示--bootstrap已禁用:那是mysql5.7以后废弃了此参数,改用--initialize来初始化了,而一般公共仓库里的sandbox ...
- 15.select into
select into SELECT INTO 语句从一个表中选取数据,然后把数据插入另一个表中. SELECT INTO 语句常用于创建表的备份复件或者用于对记录进行存档. CREATE TABLE ...
- jquery 遮罩层指定位置
.css .datagrid-mask-msg { position: absolute; top: %; margin-top: -20px; padding: 12px 5px 10px 30px ...
- 时间日期控件的处理-Selenium
很多人问时间日期的空间怎么处理,但是时间日期控件各种各样,你可能遇到正常点的像这样: 当然也可能遇到难点的,像这样: 当然,也不排除会遇到变态的,像这样: 呵呵,真要一个个想着怎么去选择,简直是非人类 ...