POJ 3977:Subset(折半枚举+二分)
【题目链接】 http://poj.org/problem?id=3977
【题目大意】
在n个数(n<36)中选取一些数,使得其和的绝对值最小.
【题解】
因为枚举所有数选或者不选,复杂度太高无法承受,
我们考虑减小枚举的范围,我们将前一半进行枚举,保存其子集和,
然后后一半枚举子集和取反在前一半中寻找最接近的,两部分相加用以更新答案。
【代码】
#include <cstdio>
#include <utility>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
const int N=40;
int n; LL a[N];
LL Abs(LL x){return x<0?-x:x;}
int main(){
while(scanf("%d",&n)&&n){
for(int i=0;i<n;i++)scanf("%lld",&a[i]);
map<LL,int> M;
map<LL,int>::iterator it;
pair<LL,int> ans(Abs(a[0]),1);
for(int i=1;i<1<<(n/2);i++){
LL s=0; int cnt=0;
for(int j=0;j*2<n;j++){if((i>>j)&1)s+=a[j],cnt++;}
ans=min(ans,make_pair(Abs(s),cnt));
if(M[s])M[s]=min(M[s],cnt);
else M[s]=cnt;
}
for(int i=1;i<1<<(n-n/2);i++){
LL s=0; int cnt=0;
for(int j=0;j<(n-n/2);j++){
if((i>>j)&1)s+=a[j+n/2],cnt++;
}ans=min(ans,make_pair(Abs(s),cnt));
it=M.lower_bound(-s);
if(it!=M.end())ans=min(ans,make_pair(Abs(s+it->first),cnt+it->second));
if(it!=M.begin()){
it--;
ans=min(ans,make_pair(Abs(s+it->first),cnt+it->second));
}
}printf("%lld %d\n",ans.first,ans.second);
}return 0;
}
POJ 3977:Subset(折半枚举+二分)的更多相关文章
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- POJ 3977 - subset - 折半枚举
2017-08-01 21:45:19 writer:pprp 题目: • POJ 3977• 给定n个数,求一个子集(非空)• 使得子集内元素和的绝对值最小• n ≤ 35 AC代码如下:(难点:枚 ...
- [poj] 3977 Subset || 折半搜索MITM
原题 给定N个整数组成的数列(N<=35),从中选出一个子集,使得这个子集的所有元素的值的和的绝对值最小,如果有多组数据满足的话,选择子集元素最少的那个. n<=35,所以双向dfs的O( ...
- POJ 3977 Subset | 折半搜索
题目: 给出一个整数集合,求出非空子集中元素和绝对值最小是多少(元素个数尽量少) 题解: 分成两半 爆搜每一半,用map维护前一半的值 每搜出后一半的一个值就去map里找和他和绝对值最小的更新答案 # ...
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- poj 3977 Subset(折半枚举+二进制枚举+二分)
Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 5721 Accepted: 1083 Descripti ...
- POJ 3977 Subset
Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 3161 Accepted: 564 Descriptio ...
- Subset POJ - 3977(折半枚举+二分查找)
题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ...
- 【折半枚举+二分】POJ 3977 Subset
题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ...
随机推荐
- HDU 4288 Coder ( 离散化 + 离线 + 线段树 )
这题跟ZOJ 3606的解题思路很相似. 题意:有3中操作:1.向集合中增加一个数x(1≤x≤1e9):2.从集合中删去一个数x(保证这个数存在):3.查询集合中所有位置满足i%5==3的数a[i]的 ...
- Android详细目录结构
Android 2.1 |-- Makefile |-- bionic (bionic C库) |-- bootable (启动引导相关代码) |-- build (存放系统编译规则及generic等 ...
- Thread suspend()挂起resume()恢复
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.Actio ...
- java安全提交笔记【xmind图片】
- LINQ to Entities 不识别方法“System int string 转换的问题
这个问题困扰了挺久,网上找了挺多方法 都太好使. 分几种情况. 1.如果查询结果 转换,那比较容易. var q = from c in db.Customers where c.Country == ...
- 应用交付工程师Troubleshooting经验分享
应用交付工程师Troubleshooting经验分享 来源:http://blog.51cto.com/virtualadc/1188328 来源:http://blog.51cto.com/virt ...
- JavaScript要理解闭包先了解词法作用域
之所以取名叫做词法作用域,是这个概念是js中相当基础也是极为重要的,很多想当然的错误或感觉怪异的问题都是和这个东西有关.所以,本文主要说下这个名词的概念以及讨论下他牵扯出来的有关变量.函数.闭包的问题 ...
- php命名空间与可变函数
命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只要避免命名重复就可以解决 对于命名空间,官方文档已经说得很详细[查看],我在 ...
- roadhogrc.mock.js配置
1.roadhogrc.mock.js const fs=require('fs'); const path=require('path'); const mockPath=path.join(__d ...
- STM in Haskell
Software Transactional Memory,软件事务内存管理(应该是这么翻译的吧T_T) 类似于数据库的事务,所有的操作都有log,最后验证其他线程是否对数据进行修改,要是有那么就回滚 ...