Subset
Time Limit: 30000MS        Memory Limit: 65536K
Total Submissions: 6754        Accepted: 1277

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

Source
Seventh ACM Egyptian National Programming Contest

题解:给出n个数,让你取出一个子集,使子集和的绝对值最小,如果有多个构成相同绝对值的方案,取子集个数最小的

求最小绝对值和最小大小

题解:数据范围可以猜出是折半枚举,前一半的数可以在len×2^(n/2)内求出,然后再暴力枚举后一半的和sum,在前一半的所有答案中找出与-sum最相近的两个数,对于sum所产生的贡献,答案肯定只会由这两个数+sum影响。当然还要考虑空集的情况,也就是只取前面或者只取后面

代码如下:

#include<map>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson ch[x][0]
#define rson ch[x][1]
#define hi puts("hi!");
#define int long long
#define mp make_pair
#define pii pair<int,int>
using namespace std; int n,len1,len2,a[];
map<int,int> m; long long absl(long long x)
{
return x>0ll?x:-x;
} signed main()
{
while(~ scanf("%lld",&n)&&n)
{
m.clear();
pii ans=mp(1e18,0ll);
for(int i=;i<n;i++) scanf("%lld",&a[i]);
len1=n/;
len2=n-len1;
for(int i=;i<<<len1;i++)
{
int cnt=,sum=;
for(int j=;j<len1;j++)
{
if(i&(<<j))
{
cnt++;
sum+=a[j];
}
}
if(!m.count(sum)||m[sum]>cnt) m[sum]=cnt;
if(ans>mp(absl(sum),cnt)) ans=mp(absl(sum),cnt);
}
for(int i=;i<<<len2;i++)
{
int cnt=,sum=;
for(int j=;j<len2;j++)
{
if(i&(<<j))
{
cnt++;
sum+=a[len1+j];
}
}
if(ans>mp(absl(sum),cnt)) ans=mp(absl(sum),cnt);
map<long long,long long>::iterator it=m.lower_bound(-sum);
if(it!=m.end())
{
if(ans>mp(absl(sum+it->first),cnt+it->second))
{
ans=mp(absl(sum+it->first),cnt+it->second);
}
}
if(it!=m.begin()) it--;
if(it!=m.end())
{
if(ans>mp(absl(sum+it->first),cnt+it->second))
{
ans=mp(absl(sum+it->first),cnt+it->second);
}
}
}
printf("%lld %lld\n",ans.first,ans.second);
}
}

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 || 折半搜索MITM

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

  3. POJ 3977 Subset | 折半搜索

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

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

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

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

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

  6. POJ 3977 Subset

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

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

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

  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. 深入理解 Express.js

    本文针对那些对Node.js有一定了解的读者.假设你已经知道如何运行Node代码,使用npm安装依赖模块.但我保证,你并不需要是这方面的专家.本文针对的是Express 3.2.5版本,以介绍相关概念 ...

  2. requests and BeautifulSoup

    requests Python标准库中提供了:urllib.urllib2.httplib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作, ...

  3. urllib2的GET和POST请求(五)

    urllib2默认只支持HTTP/HTTPS的GET和POST方法 urllib.urlencode() urllib 和 urllib2 都是接受URL请求的相关模块,但是提供了不同的功能.两个最显 ...

  4. sqlplus rlwrap readline

  5. C++Builder 内存泄露检测

    C++Builder 内存泄露检测 CodeGuard http://bbs.2cto.com/read.php?tid=179933 XE新版里 ReportMemoryLeaksOnShutdow ...

  6. 跟我学算法-吴恩达老师的logsitic回归

    logistics回归是一种二分类问题,采用的激活函数是sigmoid函数,使得输出值转换为(0,1)之间的概率 A = sigmoid(np.dot(w.T, X) + b ) 表示预测函数 dz ...

  7. JAVA_02

    class Test2_Extents{ public static void main(String[] args){ System.out.println("Hello World&qu ...

  8. U3D屏幕坐标,世界坐标,像素坐标之间的关系

    U3D中,屏幕坐标和世界坐标单位一样,二者之间是直接的一一对应关系,不受屏幕分辨率影响.默认情况下屏幕空间画布的左下角坐标是世界原点(0,0,0),这种情形下,世界空间的点(1920,1080,任何值 ...

  9. 如何快速选中某单元格所在的整行或整列 Excel教程

    我们可以使用快捷键的操作来快速选中B3单元格所在的整行或整列,操作方法如下,请大家参阅! 一.正规的快捷键操作 ①快速选中整行 按下键盘上的 Shift Space 即同时按下键盘上的Shift 空格 ...

  10. 01-E-1: 迭代与递归