【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 ...
随机推荐
- ResponseUtil
package util; import java.io.OutputStream; import java.io.PrintWriter; import javax.servlet.http.Htt ...
- component to string 自定义窗体
component to string string to component StringToComponent ComponentToString ObjectTextToBinary Objec ...
- Cause: java.sql.SQLException: 无效的列索引
今天调试代码发现“Cause: java.sql.SQLException: 无效的列索引”,查资料得出结论如下: 1.sql串的?号用''括了起来. 例如:select* from user t ...
- 微信小程序中出现Invoking Page() in async task.问题
在做项目中需要让页面跳到外网,用到了<web-view src=""> </web-view>组件,需要新建一个文件放这个组件,调接口的时候链接连到这个页面 ...
- Hadoop IO基于文件的数据结构详解【列式和行式数据结构的存储策略】
Charles所有关于hadoop的文章参考自hadoop权威指南第四版预览版 大家可以去safari免费阅读其英文预览版.本人也上传了PDF版本在我的资源中可以免费下载,不需要C币,点击这里下载. ...
- android 记录所有打开的Activity,退出程序
android 记录所有打开的Activity,退出程序 package com.main.server; import java.util.LinkedList; import java.uti ...
- python asyncio 异步实现mongodb数据转xls文件
from pymongo import MongoClient import asyncio import xlwt import json class Mongodb_Transfer_Excel( ...
- Mac hook—DYLD_INSERT_LIBRARIES
[Mac hook—DYLD_INSERT_LIBRARIES] 1.gcc生成dylib. gcc -dynamiclib -o mysharedlib.dylib mysharedlib.c 2. ...
- [luogu3391] 【模板】文艺平衡树(fhq-treap反转区间)
解题关键:无旋treap模板. #include<iostream> #include<cstdio> #include<cstring> #include< ...
- datatables01 安装、数据源、选中行事件、新增一行数据、删除一行数据
1 安装 1.1 引入必要文件 要在项目中使用datatables需要引入三个文件 >DataTables CSS >jQuery >DataTables JS <!-- Da ...