题目

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. 1
  2. 10
  3. 3
  4. 20 100 -100
  5. 0

样例输出

  1. 10 1
  2. 0 2

题解

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

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

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

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

代码

  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <map>
  4. using namespace std;
  5. #define abs(x) ((x) >= 0 ? (x) : -(x))
  6. long long arr[40];
  7. int main() {
  8. int n;
  9. while (scanf("%d", &n), n) {
  10. for (int i = 0; i < n; i++) scanf("%lld", &arr[i]);
  11. pair<long long, long long> ans(abs(arr[0]), 1);
  12. map<long long, long long> m;
  13. map<long long, long long>::iterator it;
  14. int nl = n >> 1, nr = n - (n >> 1);
  15. for (int i = 1; i < (1 << nl); i++) {
  16. long long sum = 0, cnt = 0;
  17. for (int j = 0; j < nl; j++) {
  18. if ((i >> j) & 1) sum += arr[j], cnt++;
  19. }
  20. long long sum1 = abs(sum);
  21. if (sum1 < ans.first || (sum1 == ans.first && cnt < ans.second)) ans = make_pair(sum1, cnt);
  22. if (m[sum]) m[sum] = min(m[sum], cnt);
  23. else m[sum] = cnt;
  24. }
  25. for (int i = 1; i < (1 << nr); i++) {
  26. long long sum = 0, cnt = 0;
  27. for (int j = 0; j < nr; j++)
  28. if ((i >> j) & 1) sum += arr[j + nl], cnt++;
  29. long long sum1 = abs(sum);
  30. if (sum1 < ans.first || (sum1 == ans.first && cnt < ans.second)) ans = make_pair(sum1, cnt);
  31. it = m.lower_bound(-sum);
  32. if (it != m.end()) {
  33. long long s = abs(it->first + sum), t = it->second + cnt;
  34. if (s < ans.first || (s == ans.first && t < ans.second))
  35. ans = make_pair(s, t);
  36. }
  37. if (it != m.begin()) {
  38. it--;
  39. long long s = abs(it->first + sum), t = it->second + cnt;
  40. if (s < ans.first || (s == ans.first && t < ans.second))
  41. ans = make_pair(s, t);
  42. }
  43. }
  44. printf("%lld %lld\n", ans.first, ans.second);
  45. }
  46. return 0;
  47. }

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. 一文了解Docker容器技术的操作

    一文了解Docker容器技术的操作 前言一.Docker是什么二.Docker的安装及测试Docker的安装Docker的Hello world测试三.Docker的常见操作镜像的基本操作容器的基本操 ...

  2. HttpClientFactory-向外请求的最佳

    简介 它的组件包是Microsoft.Extensions.Http 复原HttpClient带来的问题 HttpClient相关问题 虽然HttpClient类实现了IDisposable,但不是首 ...

  3. 源码分析(1)-HashMap(JDK1.8)

    UML类图 java.util.Map<K, V>接口,有4个实现类:HashMap.Hashtable.LinkedHashMap和TreeMap. 1.说明 (1)HashMap除允许 ...

  4. CSS3弹性布局内容对齐(justify-content)属性使用详解

    内容对齐(justify-content)属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线(main axis)对齐. 该操作发生在弹性长度以及自动边距被确定后. 它用来在存在剩余空间时如何加以分配 ...

  5. ios支付签名认证

    一.解析json中参数的含义 private Long id; @ApiModelProperty(value = "创建时间") private Date gmtCreate; ...

  6. 新手使用 GitHub 必备的两个神器

    一.Enhanced Github 你可能遇到过这种情况,你仅仅只想下载仓库里面的单个文件而已,但找不到下载链接,所以你只能被迫下载整个仓库. 而因为某些原因,在国内从 GitHub 上面下载代码的速 ...

  7. Java中在数字前自动补零方法

    /** * 数字前面自动补零 * @param number 数字 * @return */ public static String geFourNumber(int number){ Number ...

  8. JSON类库Jackson优雅序列化Java枚举类

    1. 前言 在Java开发中我们为了避免过多的魔法值,使用枚举类来封装一些静态的状态代码.但是在将这些枚举的意思正确而全面的返回给前端却并不是那么顺利,我们通常会使用Jackson类库序列化对象为JS ...

  9. Docker图形界面管理

    之前都是使用命令行进行Docker的管理,这里简单介绍一下Docker的图形界面管理.之所以说简单介绍,是因为在生产环境都是集群,很少使用图形界面管理单台Docker主机,所以就演示记录一下,在个人测 ...

  10. Axis WSDD文件参考文档

    本部分介绍的所有的WSDD元素的名称空间都是"http://xml.apache.org/axis/wsdd/". <deployment> 告诉Axis Engine ...