bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)
2679: [Usaco2012 Open]Balanced Cow Subsets
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 462 Solved: 197
[Submit][Status][Discuss]
Description
给出N(1≤N≤20)个数M(i) (1 <= M(i) <= 100,000,000),在其中选若干个数,如果这几个数可以分成两个和相等的集合,那么方案数加1。问总方案数。
Input
Output
Sample Input
INPUT DETAILS: There are 4 cows, with milk outputs 1, 2, 3, and 4.
Sample Output
OUTPUT DETAILS: There are three balanced subsets: the subset {1,2,3}, which can be partitioned into {1,2} and {3}, the subset {1,3,4}, which can be partitioned into {1,3} and {4}, and the subset {1,2,3,4} which can be partitioned into {1,4} and {2,3}.
HINT
Source
/*
判断能否划分为两个相等集合时用dp RE了
*/
#include<bits/stdc++.h> #define N 30
#define M 3111111
#define mod 2333333 using namespace std;
int n,m,ans,cnt,flag;
int a[N],vis[N],V[M];
int cur[N],sum[N]; inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} bool dfs2(int cur[],int k,int val,int n)
{
if(n== && cur[]!=cur[]) return false;
if(flag) return true;
if(val==sum[n]-val) {flag=;return true;}
if(k==n && !flag) return false;
for(int i=k+;i<=n;i++)
dfs2(cur,i,val+cur[i],n),dfs2(cur,i,val,n);
if(!flag)return false;
} bool judge()
{
int cnt_=,S=;
memset(cur,,sizeof cur);
memset(sum,,sizeof sum);
for(int i=;i<=n;i++) if(vis[i]) cur[++cnt_]=a[i],sum[cnt_]=sum[cnt_-]+cur[cnt_];
sort(cur+,cur+cnt_+);
for(int i=;i<=cnt_;i++) S+=S*+cur[i],S%=mod;
if(V[S]) return false;V[S]=;flag=;
if(sum[cnt_]%) return false;
if(dfs2(cur,,,cnt_)) return true;
return false; } void dfs(int lim,int k,int tot)
{
if(tot==lim)
{
if(judge()) ans++;
return;
}
if(k>n) return;
for(int i=k+;i<=n;i++)
{
if(vis[i]) continue;
vis[i]=;dfs(lim,k+,tot+);
vis[i]=;
}
} int main()
{
//freopen("ly.in","r",stdin);
n=read();
for(int i=;i<=n;i++) a[i]=read();
cnt=;
while(cnt<=n)
{
memset(vis,,sizeof vis);
dfs(cnt,,);
cnt++;
}
printf("%d\n",ans);
return ;
}
24暴搜
/*
折半搜索
枚举每个数如何选择,放入A就加,放入B就减
状压判断每个数的具体选择状态
最后双指针扫统计答案 若集合A的和 + 集合B的和为0那么就说明这两个集合构成的答案合法
*/
#include<bits/stdc++.h> #define N 22
#define ll long long using namespace std;
int n,v[N<<],maxdep,cnta,cntb;
bool vis[<<N];
ll ans;
struct node{
int state,x;
}a[<<N],b[<<N];
inline bool cmp1(node a,node b){return a.x<b.x;}
inline bool cmp2(node a,node b){return a.x>b.x;} inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} void dfs(int dep,int sum,int now,int flag)
{
if(dep==maxdep+)
{
if(!flag)
a[++cnta].x=sum,a[cnta].state=now;
else
b[++cntb].x=sum,b[cntb].state=now;
return;
}
dfs(dep+,sum,now,flag);
dfs(dep+,sum+v[dep],now | (<<(dep-)),flag);
dfs(dep+,sum-v[dep],now | (<<(dep-)),flag);
}
int main()
{
n=read();
for(int i=; i<=n; i++)v[i]=read();
maxdep=n/;dfs(,,,);
maxdep=n; dfs(n/+,,,);
sort(a+,a++cnta,cmp1);
sort(b+,b++cntb,cmp2); int l=,r=;
while(l<=cnta&&r<=cntb)
{
while(-a[l].x<b[r].x&&r<=cntb)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]=;
ans++;
}r++;
}
if(l<cnta&&a[l].x==a[l+].x)r=pos;
l++;
}
printf("%lld\n",ans-);//减去空集
return ;
}
bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)的更多相关文章
- BZOJ2679 : [Usaco2012 Open]Balanced Cow Subsets
考虑折半搜索,每个数的系数只能是-1,0,1之中的一个,因此可以先通过$O(3^\frac{n}{2})$的搜索分别搜索出两边每个状态的和以及数字的选择情况. 然后将后一半的状态按照和排序,$O(2^ ...
- 【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)
[Usaco2012 Open]Balanced Cow Subsets 题目描述 给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\) ...
- 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,于是将 ...
- bzoj2679:[Usaco2012 Open]Balanced Cow Subsets
思路:折半搜索,每个数的状态只有三种:不选.选入集合A.选入集合B,然后就暴搜出其中一半,插入hash表,然后再暴搜另一半,在hash表里查找就好了. #include<iostream> ...
- [Usaco2012 Open]Balanced Cow Subsets
Description Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk ...
- 【BZOJ】2679: [Usaco2012 Open]Balanced Cow Subsets
[算法]折半搜索+数学计数 [题意]给定n个数(n<=20),定义一种方案为选择若干个数,这些数可以分成两个和相等的集合(不同划分方式算一种),求方案数(数字不同即方案不同). [题解] 考虑直 ...
- SPOJ-SUBSET Balanced Cow Subsets
嘟嘟嘟spoj 嘟嘟嘟vjudge 嘟嘟嘟luogu 这个数据范围都能想到是折半搜索. 但具体怎么搜呢? 还得扣着方程模型来想:我们把题中的两个相等的集合分别叫做左边和右边,令序列前一半中放到左边的数 ...
- BZOJ.2679.Balanced Cow Subsets(meet in the middle)
BZOJ 洛谷 \(Description\) 给定\(n\)个数\(A_i\).求它有多少个子集,满足能被划分为两个和相等的集合. \(n\leq 20,1\leq A_i\leq10^8\). \ ...
随机推荐
- POJ-1325 Machine Schedule,和3041有着异曲同工之妙,好题!
Machine Schedule Time Limit: 1000MS Memory Limit: 10000K Description As we all know, machine ...
- Linux下汇编语言学习笔记25 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- Servlet开发(1)
Servlet开发 Servlet引入: 百度百科详细servlet介绍: 重点概括:servlet运行在服务器上,处理用户请求. 我们使用response来获取一个写方法 PrintWriter o ...
- [bzoj4300]绝世好题_二进制拆分
绝世好题 bzoj-4300 题目大意:题目链接. 注释:略. 想法: 二进制拆分然后用一个数组单独存一下当前答案即可. Code: #include <iostream> #includ ...
- [bzoj2962]序列操作_线段树_区间卷积
序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...
- Restful 级别划分以及HATEOAS是什么?
Restful简介 Rest是一种软件架构风格.设计风格,而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存 ...
- MongoDB小结18 - find【查询条件$not】
not 是元条件句,可以用于任何条件之上,意为取反
- 图片在 canvas 中的 选中/平移/缩放/旋转,包含了所有canvas的2D变化,让你认识到数学的重要性
1.介绍 canvas 已经出来好久了,相信大家多少都有接触. 如果你是前端页面开发/移动开发,那么你肯定会有做过图片上传处理,图片优化,以及图片合成,这些都是可以用 canvas 实现的. 如果你是 ...
- firemonkey获取当前文件所在路径的方法
在之前,我们知道有三种方法: ExtractFilePath(ParamStr(0)) ExtractFilePath(Application.ExeName) GetCurrentDir + '\' ...
- Cookie对象的特点
1.存储少量不重要的数据2.存储在客户端的文本文件中(必须设置有效期,否则不被存储)3.安全性差4.存储的数据类型--字符串5.浏览器窗口无关,但与访问的站点相关6.具体特定的过期时间和日期7.在客户 ...