题目

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. svg 贝塞尔曲线图解(记录)

    path路径绘制中,绘制贝塞尔曲线的命令包括: Q 二次贝赛尔曲线 x1,y1 x,y T 平滑二次贝塞尔曲线 x,y C 曲线(curveto) x1,y1 x2,y2 x,y S 平滑曲线 x2, ...

  2. 手把手带你入门numpy,从此数据处理不再慌【四】

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是numpy专题的第四篇文章,numpy中的数组重塑与三元表达式. 首先我们来看数组重塑,所谓的重塑本质上就是改变数组的shape.在保 ...

  3. MySQL 8.0权限认证(上)

    MySQL 8.0授权认证   一.系统权限表   user 存放用户账户信息以及全局级别(所有数据库)权限,决定了来自哪些主机的哪些用户可以访问数据库实例,如果有全局权限则意味着对所有数据库都有此权 ...

  4. zabbix 监控cpu 温度

    Zabbix监控Linux主机CPU温度   一.客户端 1.客户Linux主机安装Im_sensors [root@localhost ~]# yum install -y lm-sensors-y ...

  5. 内核与驱动文件的version magic匹配问题

    https://blog.csdn.net/yubing_615/article/details/52183185 1.问题:本地编译的一整套底层代码down到设备跑都正常,但是由这套代码上传SVN服 ...

  6. windows10+office2019各版本激活密钥

    [windows10激活密钥] 1.win10专业版 236TW-X778T-8MV9F-937GT-QVKBB 87VT2-FY2XW-F7K39-W3T8R-XMFGF KH2J9-PC326-T ...

  7. 非线性规划的Matlab 解法

    编写M 文件fun1.m 定义目标函数 function f=fun1(x); % 定义目标函数 f=sum(x.^)+; % .^2是矩阵中的每个元素都求平方.^2是求矩阵的平方或两个相同的矩阵相乘 ...

  8. 2019-01-31 Python学习之BFS与DFS实现爬取邮箱

    今天学习了python网络爬虫的简单知识 首先是一个爬取百度的按行读取和一次性爬取 逐行爬取 for line in urllib.request.urlopen("http://www.b ...

  9. 基础拾遗---委托,匿名函数,lambda

    前言: C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针.委托是存有对某个方法的引用的一种引用类型变量.引用可在运行时被改变.委托(Delegate)特别用于实现事件和回调方法. ...

  10. Nginx配置rewrite过程介绍

    创建rewrite语句 vi conf/vhost/www.abc.com.conf #vi编辑虚拟主机配置文件 文件内容 server { listen 80; server_name abc.co ...