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. fork()、vfork()、clone()和exec()

    前三个和最后一个是两个类型.前三个主要是Linux用来创建新的进程(线程)而设计的,exec()系列函数则是用来用指定的程序替换当前进程的所有内容.所以exec()系列函数经常在前三个函数使用之后调用 ...

  2. /etc/sysctl.conf参数解释(转)

    来自<深入理解Nginx模块开发与架构解析> P9 #表示进程(例如一个worker进程)可能同时打开的最大句柄数,直接限制最大并发连接数fs.file max = 999999 #1代表 ...

  3. python笔记--2018-2019

    一:读取json文件的方法 import json json.loads(open('./users.dev.json', 'r').read())     #获取文件的类容,并且序列化把看似列表的字 ...

  4. Poly

    folly/Poly.h Poly is a class template that makes it relatively easy to define a type-erasing polymor ...

  5. guicorn 是什么

    guicorn 是什么? 在回答问题之前我们先来看看 web服务器的典型过程[1] 1. 建立链接:如果没有连接,要建立连接 2. 接收请求:对客户端发来的请求进行解析. 3. 处理请求:转发给预定义 ...

  6. Pthreads 《并行程序设计导论》的补充代码

    ▶ 关于单链表的访问,插入结点和删除结点操作,并且将其推广到多线程中去. ● 代码,通用的随机数生成 // my_rand.h #ifndef _MY_RAND_H_ #define _MY_RAND ...

  7. 263. Ugly Number + 264. Ugly Number II + 313. Super Ugly Number

    ▶ 三个与丑数相关的问题 ▶ 第 263题,判定一个数字是否是丑数,即其素因子是否仅由 2,3,5 构成. ● 常规消除判别,4 ms class Solution { public: bool is ...

  8. 使用ES-Hadoop 6.5.4编写MR将数据索引到ES

    目录 1. 开发环境 2. 下载地址 3. 使用示例 4. 参考文献 1. 开发环境 Elasticsearch 6.5.4 ES-Hadoop 6.5.4 Hadoop 2.0.0 2. 下载地址 ...

  9. 使用Visual Studio进行 Android开发的十大理由

    [原文发表地址]Top 10 reasons to use Visual Studio for C++ Android Development! Visual Studio: C++跨平台的移动解决方 ...

  10. Thrift分析

    [Thrift分析] Thrift定义一套IDL(Interface Definition Language)用于描述接口,通常后缀名为.thrift,通过thrift程序把.thrift文件导出成各 ...