Subset

Time Limit: 30000MS Memory Limit: 65536K

Total Submissions: 5961 Accepted: 1129

Description

Given a list of N integers with absolute values no larger than 1015, find a non empty subset of these numbers which minimizes the absolute value of the sum of its elements. In case there are multiple subsets, choose the one with fewer elements.

Input

The input contains multiple data sets, the first line of each data set contains N <= 35, the number of elements, the next line contains N numbers no larger than 1015 in absolute value and separated by a single space. The input is terminated with N = 0

Output

For each data set in the input print two integers, the minimum absolute sum and the number of elements in the optimal subset.

Sample Input

1

10

3

20 100 -100

0

Sample Output

10 1

0 2


解题心得:

  1. 就是一个双向搜索,要求的是选择出来的元素的总和的绝对值最小,按照双向搜索的思路去做就可以了。但是要注意的一点是在二分搜索最相近的答案的时候可能从这个数的lower_bound产生的结果,或者lower_bound的位置-1产生绝对值最小的答案。

#include <algorithm>
#include <cstring>
#include <map>
#include <stdio.h>
using namespace std;
typedef long long ll;
const ll maxn = 45;
const ll MAX = 1e15; map <ll,ll> M;
pair <ll,ll> ans;
ll n,num[maxn]; ll Abs(ll x) {
if(x < 0)
return -x ;
return x;
} void init() {
M.clear();
ans = make_pair(MAX,MAX);
for(int i=0;i<n;i++) scanf("%lld",&num[i]);
} void get_sum(ll mid) {
ll cnt,sum;
for(ll i=1;i<(1<<mid);i++) {
cnt = sum = 0;
for(ll j=0;j<mid;j++) {
if(1&(i>>j)) {
sum += num[j];
cnt++;
}
}
ans = min(ans,make_pair(Abs(sum),cnt));
if(M[sum]) {
M[sum] = min(M[sum],cnt);
} else
M[sum] = cnt;
}
} void solve(ll mid) {
map<ll,ll> :: iterator iter;
for(ll i=1;i<(1<<(n-mid));i++) {
ll sum,cnt;
sum = cnt = 0;
for(int j=0;j<(n-mid);j++) {
if(1&(i>>j)) {
sum += num[mid+j];
cnt++;
}
}
ans = min(ans,make_pair(Abs(sum),cnt)); iter = M.lower_bound(-sum);
if(iter != M.end()) {
ans = min(ans,make_pair(Abs(iter->first+sum),cnt+iter->second));
}
if(iter != M.begin()) {
iter--;
ans = min(ans,make_pair(Abs(iter->first+sum),iter->second+cnt));
}
}
printf("%lld %lld\n",ans.first,ans.second);
} int main() {
while(scanf("%lld",&n) && n) {
init();
ll mid = n>>1;
get_sum(mid);
solve(mid);
}
return 0;
}

POJ:3977-Subset(双向搜索)的更多相关文章

  1. POJ 3977 - subset - 折半枚举

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

  2. POJ 3977 Subset

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

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

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

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

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

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

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

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

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

  7. POJ 3977 Subset | 折半搜索

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

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

    题意:有一个N(N <= 35)个数的集合,每个数的绝对值小于等于1015,找一个非空子集,使该子集中所有元素的和的绝对值最小,若有多个,则输出个数最小的那个. 分析: 1.将集合中的元素分成两 ...

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

    [题目链接] http://poj.org/problem?id=3977 [题目大意] 在n个数(n<36)中选取一些数,使得其和的绝对值最小. [题解] 因为枚举所有数选或者不选,复杂度太高 ...

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

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

随机推荐

  1. angular2-搭建环境

    npm  模块将被下载安装到[全局目录]中.[全局目录]通过 npm config set prefix "目录路径" 来设置.通过 npm config get prefix 来 ...

  2. C++ Knowledge series 4

    Programming language evolves always along with Compiler's evolvement The Semantics of Function C++ s ...

  3. sharepoint知识点总结

    { users.Add(value.User); } else { SPGroup group = web.Groups.GetByID(value.LookupId); groups.Add(gro ...

  4. Extjs4如何构造store基类

    目标:重写一个BaseStore的基类,它继承自Ext.data.Store基类. autoLoad:true/false 是否自动加载,true时创建store即自动加载,一般适合get方式:fal ...

  5. So you want to write a desktop app in Python

    So you want to write a desktop app in Python Thomas Kluyver 2014-06-16 23:55 51 Comments Source This ...

  6. 概念:RPG游戏中两个兵种互相攻击的逻辑

    直接上题目: 解析题目: 根据题目的解析,进行代码的实现: 输出结果: 心得: (1) 当我们面对‘公式结果不是我们想要的’时,应该在脑海里将一个完整的攻击流程进行想象,就会对流程有个更清晰的思路 ( ...

  7. PointCNN 论文翻译解析

    1. 前言 卷积神经网络在二维图像的应用已经较为成熟了,但 CNN 在三维空间上,尤其是点云这种无序集的应用现在研究得尤其少.山东大学近日公布的一项研究提出的 PointCNN 可以让 CNN 在点云 ...

  8. Altium_Designer如何快速寻找元件和封装

    初学Altium碰到最多的问题就是:不知道元件放在哪个库中.这里我收集了DXP2004常用元件库下常见的元件.使用时,只需在libary中选择相应元件库后,输入英文的前几个字母就可看到相应的元件了.通 ...

  9. Convolutional Neural Networks from deep learning (assignment 1 from week 1)

    Convolutional Neural Networks https://www.coursera.org/learn/convolutional-neural-networks/home/welc ...

  10. vuejs父子组件的数据传递

    在vue中,父组件往子组件传递参数都是通过属性的形式来传递的 <div id='root'> <counter :count = '1'></counter> &l ...