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\). \ ...
随机推荐
- noip模拟赛 星空
分析:非常神的一道题.迭代加深搜索+rand可以骗得20分.状压n的话只有24分,必须对问题进行一个转化. 在爆搜的过程中,可以利用差分来快速地对一个区间进行修改,把一般的差分改成异或型的差分: b[ ...
- 食物(bzoj 3280)
Description 明明这次又要出去旅游了,和上次不同的是,他这次要去宇宙探险! 我们暂且不讨论他有多么NC,他又幻想了他应该带一些什么东西.理所当然的,你当然要帮他计算携带N件物品的方案数. 他 ...
- 国王游戏(codevs 1198)
题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王站在队伍的最 ...
- 「CodePlus 2017 11 月赛」Yazid 的新生舞会
n<=500000的数字,问有多少个区间的众数出现次数严格大于区间长度的一半. 这么说来一个区间就一个众数了,所以第一反应是枚举数字,对下标进行处理.然后没有第二反应.很好. 在枚举一个数字的时 ...
- 基于xml配置springmvc
controller关键代码 public class MenuController extends MultiActionController 方法: public ModelAndView lis ...
- java文件工具类
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.Fi ...
- sqlalchemy多表联合查询的左连接、右连接等使用
#按用户名摸糊查询trans_details.query.join(Uses).filter(Users.username.like('%xx%'))#select xxx from trans_de ...
- #!/usr/bin/env 脚本解释程序的作用
the Zimbu programming language http://www.zimbu.org/getting-started -------------------------------- ...
- phpunit 单元测试框架-代码覆盖率
"phpize not found" 的解决办法: apt-get install php5-dev http://jeffreysambells.com/2010/04/08/r ...
- vux 实现多栏滚动
1.PopupPicker 组件 <!-- vux-ui --> <template> <div> <!-- 标题栏 --> <x-header ...