[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]世界冰球锦标赛

BZOJ链接洛谷链接 附加my blog

这道题有三种状态

  1. 不放入任何集合
  2. 放入左边集合
  3. 放入右边集合

在搜索时如何表示呢,我们可以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(折半搜索+双指针)的更多相关文章

  1. bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)

    2679: [Usaco2012 Open]Balanced Cow Subsets Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 462  Solv ...

  2. 【BZOJ】2679: [Usaco2012 Open]Balanced Cow Subsets

    [算法]折半搜索+数学计数 [题意]给定n个数(n<=20),定义一种方案为选择若干个数,这些数可以分成两个和相等的集合(不同划分方式算一种),求方案数(数字不同即方案不同). [题解] 考虑直 ...

  3. 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 ...

  4. 折半搜索+Hash表+状态压缩 | [Usaco2012 Open]Balanced Cow Subsets | BZOJ 2679 | Luogu SP11469

    题面:SP11469 SUBSET - Balanced Cow Subsets 题解: 对于任意一个数,它要么属于集合A,要么属于集合B,要么不选它.对应以上三种情况设置三个系数1.-1.0,于是将 ...

  5. [Usaco2012 Open]Balanced Cow Subsets

    Description Farmer John's owns N cows (2 <= N <= 20), where cow i produces M(i) units of milk ...

  6. BZOJ2679 : [Usaco2012 Open]Balanced Cow Subsets

    考虑折半搜索,每个数的系数只能是-1,0,1之中的一个,因此可以先通过$O(3^\frac{n}{2})$的搜索分别搜索出两边每个状态的和以及数字的选择情况. 然后将后一半的状态按照和排序,$O(2^ ...

  7. bzoj2679:[Usaco2012 Open]Balanced Cow Subsets

    思路:折半搜索,每个数的状态只有三种:不选.选入集合A.选入集合B,然后就暴搜出其中一半,插入hash表,然后再暴搜另一半,在hash表里查找就好了. #include<iostream> ...

  8. SPOJ-SUBSET Balanced Cow Subsets

    嘟嘟嘟spoj 嘟嘟嘟vjudge 嘟嘟嘟luogu 这个数据范围都能想到是折半搜索. 但具体怎么搜呢? 还得扣着方程模型来想:我们把题中的两个相等的集合分别叫做左边和右边,令序列前一半中放到左边的数 ...

  9. codeforces912E(折半搜索+双指针+二分答案)

    E. Prime Gift E. Prime Gift time limit per test 3.5 seconds memory limit per test 256 megabytes inpu ...

随机推荐

  1. 在ubuntu中编译内核是用make&nbsp;…

    执行过程如下: root@zyx-VirtualBox:~# cd /opt/EmbedSky/ root@zyx-VirtualBox:/opt/EmbedSky# cd linux-2.6.30. ...

  2. Python文件修改和常用方法

    为了更好地说明接下来的文件修改操作,我们有必要先来学习下文件操作的常用方法. 一.文件处理中的常用方法 #!/usr/bin/env python3 #-*- coding:utf-8 -*- # w ...

  3. 4-1 线程安全性-原子性-atomic-1

    我们发现在不做任何同步的情况下,我们计算的累加结果是错误的. com.mmall.concurrency.example.count.CountExample2 C:\Users\ZHONGZHENH ...

  4. 刷题向》关于一道奇怪的贪心(田忌赛马)BZOJ1034(NORMAL-)

    这道题一看就是一道贪心,比较简单,但是越容易的题考试的时候越容易错... 没什么好说的,一遍SORT之后,直接强行田忌赛艇(滑稽脸)就好啦. 注意在对比大小的时候不仅要从前还要从后同时,不过这两个情况 ...

  5. 对输入字符进行HTML转义 OR  去HTML标签

    /** * 对输入字符进行HTML转义 * @param mixed $data */ public static function escape($data) { if(is_array($data ...

  6. 535. Encode and Decode TinyURL 长短URL

    [抄题]: TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problem ...

  7. Django--admin后台

    需求 通过后台和models​操作数据库表 实现 1.后台中看到数据库中的表 app01/admin.py 1 2 from app01 import models admin.site.regist ...

  8. 2.python IP/DNS地址处理之IPy/Dnspython模块

     1.IPy模块 在IP地址规划中,涉及到计算大量的IP地址,包括网段.网络掩码.广播地址.子网数.IP类型等,即便是专业的网络人员也要进行繁琐的计算,而IPy模块提供了专门针对IPV4地址与IPV6 ...

  9. 运行maven build报错No goals have been specified for this build.

    运行maven报错: [ERROR] No goals have been specified for this build. You must specify a valid lifecycle p ...

  10. (转)基于 WPF + Modern UI 的 公司OA小助手 开发总结

    原文地址:http://www.cnblogs.com/rainlam163/p/3365181.html 前言: 距离上一篇博客,整整一个月的时间了.人不能懒下来,必须有个阶段性的总结,算是对我这个 ...