SPOJ11469 Subset(折半枚举)
题意
给定一个集合,有多少个非空子集,能划分成和相等的两份。$n\leq 20$
题解
看到这个题,首先能想到的是$3n$的暴力枚举,枚举当前元素是放入左边还是放入右边或者根本不放,但是显然是不可取的,看到$n$只有20,考虑折半搜索,将集合分成两部分,每个部分$3{\frac{n}{2}}$枚举。
接着考虑如何合并,在枚举时计一个$delta$表示此时左边和右边的差值,这样在右半部分每一次枚举完后我们可以直接在左半部分查找是否存在一个$delta$相等,如果相等,则两个集合的并集满足条件
#include <map>
#include <vector>
#include <cstdio>
typedef long long ll;
template <typename T>
inline void read(T &x) {
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
}
const int N = 21;
int n, m, a[N], cnt, ans;
std::map <int, int> Ma;
std::vector <int> S[1 << N];
bool ok[1 << N];
void dfs1(int i, int s, int d) {
if (i > m) {
if (Ma.find(d) == Ma.end()) Ma[d] = ++cnt;
int index = Ma[d];
//记录delta,由于可能存在多个相等的delta,开一个vector记下它是哪个集合(状态压缩)
S[index].push_back(s);
return ;
}
dfs1(i + 1, s, d);
dfs1(i + 1, s | (1 << i), d + a[i]);
dfs1(i + 1, s | (1 << i), d - a[i]);
}
void dfs2(int i, int s, int d) {
if (i > n) {
if (Ma.find(d) == Ma.end()) return ;
int index = Ma[d];
std::vector<int>::iterator it;
//直接查询然后置他们的并集为真即可
for (it = S[index].begin(); it != S[index].end(); ++it)
ok[*it | s] = true;
return ;
}
dfs2(i + 1, s, d);
dfs2(i + 1, s | (1 << i), d + a[i]);
dfs2(i + 1, s | (1 << i), d - a[i]);
}
int main () {
read(n); m = n >> 1;
for(int i = 1; i <= n; ++i) read(a[i]);
dfs1(1, 0, 0);
dfs2(m + 1, 0, 0);
for(int i = (1 << (n + 1)) - 1; i >= 1; --i)
ans += ok[i];
printf("%d\n", ans);
return 0;
}
SPOJ11469 Subset(折半枚举)的更多相关文章
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- POJ3977 Subset 折半枚举
题目大意是给定N个数的集合,从这个集合中找到一个非空子集,使得该子集元素和的绝对值最小.假设有多个答案,输出元素个数最少的那个. N最多为35,假设直接枚举显然是不行的. 可是假设我们将这些数分成两半 ...
- POJ 3977 - subset - 折半枚举
2017-08-01 21:45:19 writer:pprp 题目: • POJ 3977• 给定n个数,求一个子集(非空)• 使得子集内元素和的绝对值最小• n ≤ 35 AC代码如下:(难点:枚 ...
- poj 3977 Subset(折半枚举+二进制枚举+二分)
Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 5721 Accepted: 1083 Descripti ...
- Load Balancing 折半枚举大法好啊
Load Balancing 给出每个学生的学分. 将学生按学分分成四组,使得sigma (sumi-n/4)最小. 算法: 折半枚举 #include <iostrea ...
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- NYOJ 1091 超大01背包(折半枚举)
这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序 ...
- Codeforces 888E - Maximum Subsequence(折半枚举(meet-in-the-middle))
888E - Maximum Subsequence 思路:折半枚举. 代码: #include<bits/stdc++.h> using namespace std; #define l ...
- Codeforces 912 E.Prime Gift (折半枚举、二分)
题目链接:Prime Gift 题意: 给出了n(1<=n<=16)个互不相同的质数pi(2<=pi<=100),现在要求第k大个约数全在所给质数集的数.(保证这个数不超过1e ...
- poj_3977 折半枚举
题目大意 给定N(N<=35)个数字,每个数字都<= 2^15. 其中一个或多个数字加和可以得到s,求出s的绝对值的最小值,并给出当s取绝对值最小值时,需要加和的数字的个数. 题目分析 需 ...
随机推荐
- 2015/8/30 Python基础(4):序列操作符
序列是指成员有序排列,可以通过下标偏移量访问的类型.Python序列包括:字符串.列表和元组.序列的每个元素可以指定一个偏移量得到,多个元素是通过切片操作得到的.下标偏移量从0开始计数到总数-1结束. ...
- mvc BundleConfig实现对Css、Js压缩打包加载
Bundle不是.net Framework框架中的一员,使用Bundle首先要先添加引用,如下: nuget包管理--程序包管理控制台--Install-Package Microsoft.AspN ...
- android程序员成长路径的思考
我之前就想过要写这个话题,不过之前没有什么认识,我只是在阅读别人的见解,看法.昨天晚上,我阅读了这篇文章<产品经理罗永浩:用户体验探索,没有尽头>,这篇文章描述了罗永浩对锤子手机设计细节的 ...
- 【BZOJ4517】【SDOI2016】排列计数 [数论]
排列计数 Time Limit: 60 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 求有多少种长度为 n 的序列 A, ...
- 【CF558E】 A Simple Task (权值线段树)
题目链接 用权值线段树维护每个字母在\([l,r]\)出现的次数,每次修改把每个字母在区间的出现次数记下来,然后清空这段区间,再按顺序插进去就好了. 时间复杂度\(O(n\log n*26)\) (好 ...
- Javascript prototype 及 继承机制的设计思想
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...
- 总有你要的编程书单(GitHub )
目录 IDE IntelliJ IDEA 简体中文专题教程 MySQL 21分钟MySQL入门教程 MySQL索引背后的数据结构及算法原理 NoSQL Disque 使用教程 Neo4j .rb 中文 ...
- hdu 1556(线段树之扫描线)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556 Color the ball Time Limit: 9000/3000 MS (Java/Ot ...
- 8.0docker的客户端和守护进程
C/S 链接的方式 unix:///var/run/docker.sock 默认的 tcp://host:port fd://socketfd 在linux上进行socket 模拟 nc -U /va ...
- Linux实际用户(组)ID,有效用户(组)ID,设置用户(组)ID
实际用户(组)ID: 标识用户是谁,这两个字段在登录时取自口令文件中的登录项. 有效用户(组)ID: 决定了对文件的访问权限,通常有效用户(组)ID等于实际用户(组)ID,谁运行有效ID就等于谁的实际 ...