题目

Given a list of N integers with absolute values no larger than \(10^{15}\), 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.

输入格式

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 10 15 in absolute value and separated by a single space. The input is terminated with N = 0

输出格式

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

样例输入

1
10
3
20 100 -100
0

样例输出

10 1
0 2

题解

我自己想的话,除了暴力没有别的办法,看了题解,照着打了一遍代码,才能理解这个解法

具体思想就是,全都暴力会超时,所以分成两半枚举,左半部分枚举完保存,右半部分枚举后在左半部分二分查询。

这算优化暴力吗,dalao们的暴力也和我的暴力不一样。。。

这个代码使用了不少STL也是一个学习STL的机会

代码

#include <algorithm>
#include <cstdio>
#include <map>
using namespace std;
#define abs(x) ((x) >= 0 ? (x) : -(x))
long long arr[40];
int main() {
int n;
while (scanf("%d", &n), n) {
for (int i = 0; i < n; i++) scanf("%lld", &arr[i]);
pair<long long, long long> ans(abs(arr[0]), 1);
map<long long, long long> m;
map<long long, long long>::iterator it;
int nl = n >> 1, nr = n - (n >> 1);
for (int i = 1; i < (1 << nl); i++) {
long long sum = 0, cnt = 0;
for (int j = 0; j < nl; j++) {
if ((i >> j) & 1) sum += arr[j], cnt++;
}
long long sum1 = abs(sum);
if (sum1 < ans.first || (sum1 == ans.first && cnt < ans.second)) ans = make_pair(sum1, cnt);
if (m[sum]) m[sum] = min(m[sum], cnt);
else m[sum] = cnt;
}
for (int i = 1; i < (1 << nr); i++) {
long long sum = 0, cnt = 0;
for (int j = 0; j < nr; j++)
if ((i >> j) & 1) sum += arr[j + nl], cnt++;
long long sum1 = abs(sum);
if (sum1 < ans.first || (sum1 == ans.first && cnt < ans.second)) ans = make_pair(sum1, cnt);
it = m.lower_bound(-sum);
if (it != m.end()) {
long long s = abs(it->first + sum), t = it->second + cnt;
if (s < ans.first || (s == ans.first && t < ans.second))
ans = make_pair(s, t);
}
if (it != m.begin()) {
it--;
long long s = abs(it->first + sum), t = it->second + cnt;
if (s < ans.first || (s == ans.first && t < ans.second))
ans = make_pair(s, t);
}
}
printf("%lld %lld\n", ans.first, ans.second);
}
return 0;
}

POJ 3977 题解的更多相关文章

  1. POJ 3977 - subset - 折半枚举

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

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

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

  3. POJ 3977 折半枚举

    链接: http://poj.org/problem?id=3977 题意: 给你n个数,n最大35,让你从中选几个数,不能选0个,使它们和的绝对值最小,如果有一样的,取个数最小的 思路: 子集个数共 ...

  4. POJ 3977 Subset

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

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

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

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

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

  7. POJ 3977 Subset | 折半搜索

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

  8. poj 3744 题解

    题目 题意: $ yyf $ 一开始在 $ 1 $ 号节点他要通过一条有 $ n $ 个地雷的道路,每次前进他有 $ p $ 的概率前进一步,有 $ 1-p $ 的概率前进两步,问他不领盒饭的概率. ...

  9. poj 3061 题解(尺取法|二分

    题意 $ T $ 组数据,每组数据给一个长度 $ N $ 的序列,要求一段连续的子序列的和大于 $ S $,问子序列最小长度为多少. 输入样例 2 10 15 5 1 3 5 10 7 4 9 2 8 ...

随机推荐

  1. spring cloud 集成分布式配置中心 apollo(单机部署apollo)

    一.什么是apollo? Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用 ...

  2. electron-vue报错:Webpack ReferenceError: process is not defined

    electron-vue报错:Webpack ReferenceError: process is not defined 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总 ...

  3. numpy.stack和numpy.concatenate的区别

    在使用numpy进行矩阵运算的时候踩到的坑,原因是不能正确区分numpy.concatenate和numpy.stack在功能上的差异. 先说numpy.concatenate,直接看文档: nump ...

  4. python_lesson1 数学与随机数 (math包,random包)

    math包 math包主要处理数学相关的运算.math包定义了两个常数: math.e   # 自然常数e math.pi  # 圆周率pi   此外,math包还有各种运算函数 (下面函数的功能可以 ...

  5. cb40a_c++_STL_算法_交换swap_ranges

    cb40a_c++_STL_算法_交换swap_rangesswap_ranges(b,e,b2);如果两个容器的数据数量不一致时,只交换一部分数据,a里面3个,b里面5个,则只会交换3个,b里面还有 ...

  6. cb16a_c++_顺序容器的选用_排序_二分查找

    /*cb16a_c++_顺序容器的选用_排序_二分查找顺序容器: 1.vector的优点与缺点 vector优点:排序利用下标,快速排序,做二分查找非常快 2.list的优点与缺点 list优点:插入 ...

  7. cb03a_c++_数据结构_顺序容器_STL_stack

    /*cb03a_c++_数据结构_顺序容器_STL_stack堆栈:LIFO--Last In First Out后进先出,用于系统程序设计自适应容器(容器适配器),不是独立的容器,是一个适配器栈适配 ...

  8. Spring Boot 整合 Apollo

    简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理场景 ...

  9. 4、struct2的支持团队开发

    在一个大型的项目中,不同的人都开发不同的模块,不能所有的人都去操作同一个struct.xml文件,我们应该对于不同的模块对应不同的配置文件 列如我们对应的登陆模块,我们可以编写一个登陆的配置文件 1. ...

  10. java读写Excel模板文件,应用于负载均衡多个服务器

    首先,需要大家明白一点,对于多服务器就不能用导出文件用a标签访问链接方式去导出excel文件了,原因相信大家也明白,可能也做过尝试. 现在开始第一步:get请求,productPath 为你的项目路径 ...