【题目链接】 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(折半枚举+二分)的更多相关文章

  1. POJ 3977 Subset(折半枚举+二分)

    SubsetTime Limit: 30000MS        Memory Limit: 65536KTotal Submissions: 6754        Accepted: 1277 D ...

  2. POJ 3977 - subset - 折半枚举

    2017-08-01 21:45:19 writer:pprp 题目: • POJ 3977• 给定n个数,求一个子集(非空)• 使得子集内元素和的绝对值最小• n ≤ 35 AC代码如下:(难点:枚 ...

  3. [poj] 3977 Subset || 折半搜索MITM

    原题 给定N个整数组成的数列(N<=35),从中选出一个子集,使得这个子集的所有元素的值的和的绝对值最小,如果有多组数据满足的话,选择子集元素最少的那个. n<=35,所以双向dfs的O( ...

  4. POJ 3977 Subset | 折半搜索

    题目: 给出一个整数集合,求出非空子集中元素和绝对值最小是多少(元素个数尽量少) 题解: 分成两半 爆搜每一半,用map维护前一半的值 每搜出后一半的一个值就去map里找和他和绝对值最小的更新答案 # ...

  5. CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。

    1514: Packs Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 61  Solved: 4[Submit][Status][Web Board] ...

  6. poj 3977 Subset(折半枚举+二进制枚举+二分)

    Subset Time Limit: 30000MS   Memory Limit: 65536K Total Submissions: 5721   Accepted: 1083 Descripti ...

  7. POJ 3977 Subset

    Subset Time Limit: 30000MS   Memory Limit: 65536K Total Submissions: 3161   Accepted: 564 Descriptio ...

  8. Subset POJ - 3977(折半枚举+二分查找)

    题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ...

  9. 【折半枚举+二分】POJ 3977 Subset

    题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ...

随机推荐

  1. 1043 Is It a Binary Search Tree (25 分)(二叉查找树)

    #include<bits/stdc++.h> using namespace std; typedef struct node; typedef node *tree; struct n ...

  2. 【多线程学习(1)】创建java多线程

    1)java多线程的创建方式有三种: 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口 第一种: //继承Thread类 class ExtendsThread ex ...

  3. beta版本前准备

    目录 过去存在的问题 任务分工 开发规范 后端总结 卉卉 家灿 前端总结 绪佩 青元 恺琳 宇恒 丹丹 算法&API接口 家伟 鸿杰 一好 文档&博客撰写 政演 产品功能 我们已经做了 ...

  4. ocrosoft Contest1316 - 信奥编程之路~~~~~第三关 问题 I: 寻找大富翁

    http://acm.ocrosoft.com/problem.php?cid=1316&pid=8 题目描述 浙江杭州某镇共有n个人,请找出该镇上的前m个大富翁. 输入 输入包含多组测试用例 ...

  5. CentOS7 设置开机直接进入命令行界面

    上网查询centsos设置开机直接进入命令行界面的方法都说修改/etc/inittab文件,将文件中的“ :id:5:initdefault:”改为“ :id:3:initdefault:”,即将默认 ...

  6. RabbitMQ磁盘警报

    RabbitMQ磁盘警报 当可用磁盘空间低于配置的限制(默认为50MB)时,将触发警报,所有生产者将被阻止.目标是避免填满整个磁盘,这将导致节点上的所有写操作失败,并可能导致RabbitMQ终止.为了 ...

  7. js剪贴板操作

    这是一个很有意思的地方,很多不了解的人或者初级的js编程者会觉得很不可思议,js都那么强大了,访问剪贴板一个粘贴复制,大概就是一行命令的事情,但是事实如此,js对于访问本地计算机的剪贴板的支持其实是十 ...

  8. JS 问题整理 (1)

    监听frame加载完毕 兼容Firefox/Opera/Safari/IE的处理方式,原文链接 var oFrm = document.getElementById('ifrm'); oFrm.onl ...

  9. 小红帽的画笔(NOIP模拟赛Round 7)

    又到了神奇的模拟赛时间~ 真是丧~ 好吧我们来看看题目 小红帽是Pop star上最著名的人类画家,她可以将任何画出的东西变成真实的物品.赋予她这样神奇能力的正是她手上的画笔. 小红帽每次作画时,都需 ...

  10. 如何通过友盟分析发布后App崩溃日志

    http://blog.csdn.net/totogo2010/article/details/39892467 要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件.这个文件包含了 ...