Subset
Time Limit: 30000MS   Memory Limit: 65536K
Total Submissions: 1373   Accepted: 228

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

 
 
把集合分成两个 N / 2的集合,然后生成一种一个集合2 ^ (n - 1)种状态的和,对于另一个集合的所有状态的和 在前一个集合中二分找到一个最接近的
并找到集合元素最小的即是所求答案
 
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <utility> using namespace std; typedef long long ll;
typedef pair<ll,int> pii; const ll INF = (1e17) + ;
const int MAX = ; int N;
ll w[MAX];
pii ps[( << ) + ];
int cal[ << ],dx[] = {-,-,,}; ll Abs(ll x) {
return x > ? x : -x;
} void init() {
for(int s = ; s < ( << ); ++s) {
int sum = ;
for(int i = ; i < ; ++i) {
if(s >> i & ) ++sum;
}
cal[s] = sum;
}
}
void solve() {
int n = N / ;
ll sw = ;
for(int s = ; s < ( << n); ++s) {
sw = ;
for(int j = ; j < n; ++j) {
if(s >> j & ) sw += w[j];
}
ps[s] = make_pair(sw,cal[s]);
}
sort(ps,ps + ( << n)); int n1 = N - n;
ll ansv = INF;
int anss = N;
for(int s = ; s < ( << n1); ++s) {
sw = ;
for(int j = n; j < N; ++j) {
if(s >> (j - n) & ) sw += w[j];
}
int pos = lower_bound(ps,ps + ( << n),make_pair(-sw,-)) - ps;
ll v = INF,t = INF;
for(int i = ; i < ; ++i) {
int id = pos + dx[i];
if(id >= && id < ( << n)
&& (ps[id].second || s)) {
if(Abs(ps[id].first + sw) < t) {
t = Abs(ps[id].first + sw);
v = ps[id].first;
}
}
}
pos = lower_bound(ps,ps + ( << n),make_pair(v,-)) - ps;
if(s == && ps[pos].second == ) ++pos;
if(ansv > Abs(v + sw) || ansv == Abs(v + sw) && anss > cal[s] + ps[pos].second) {
ansv = Abs(v + sw);
anss = cal[s] + ps[pos].second;
}
} printf("%I64d %d\n",ansv,anss);
} int main()
{
freopen("sw.in","r",stdin);
init();
while(~scanf("%d",&N) && N) {
for(int i = ; i < N; ++i) scanf("%I64d",&w[i]);
solve();
} return ;
}

POJ 3977的更多相关文章

  1. POJ 3977 - subset - 折半枚举

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

  2. POJ 3977 折半枚举

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

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

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

  4. POJ 3977 Subset

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

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

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

  6. 【折半枚举+二分】POJ 3977 Subset

    题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ...

  7. Divide and conquer:Subset(POJ 3977)

    子序列 题目大意:给定一串数字序列,要你从中挑一定个数的数字使这些数字和绝对值最小,求出最小组合数 题目的数字最多35个,一看就是要数字枚举了,但是如果直接枚举,复杂度就是O(2^35)了,显然行不通 ...

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

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

  9. poj 3977 子集

    题目 题意:在一个集合中找到一个非空子集使得这个子集元素和的绝对值尽量小,和绝对值相同时保证元素个数尽量小 分析:1.二分枚举的思想,先分成两个集合: 2.枚举其中一个集合中所有的子集并且存到数组中, ...

随机推荐

  1. Yii2 实现修改密码功能

    YII2对密码加密生成的结果是不同的,即用相同的初始密码在不同时间得到的加密结果不同,所以我们不能用常用的方法去验证密码是否正确(将密码加密后与数据库中的密码相比较).YII2有自己的加密以及密码验证 ...

  2. USACO 3.2 kimbits DP

    自己YY了个DP:设f[n][l]为n位数中包含不超过l个1的总个数 f[n][l]=f[n-1][l]+f[n-1][l-1] 然后用_search()从高位向低位扫描即可,tmp记录当前已记下多少 ...

  3. c++内存分配(new和delete)

    c中malloc和free是函数,包含在stdlib.h头文件中,分配成功返回指针,失败返回空指针. 与new的区别是: 1,malloc与free是C++/C语言的标准库函数,new/delete是 ...

  4. p2p软件如何穿透内网进行通信

    http://blog.chinaunix.net/uid-22326462-id-1775108.html 首先先介绍一些基本概念: NAT(Network Address Translators) ...

  5. java + jquery + ajax + json 交互

    前端js部分: $.ajax({ async:true, cache:false, type:"POST", dataType : 'json', url:"/shopp ...

  6. MySQL 存储过程传参之in, out, inout 参数用法

    存储过程传参:存储过程的括号里,可以声明参数. 语法是 create procedure p([in/out/inout] 参数名  参数类型 ..) in :给参数传入值,定义的参数就得到了值 ou ...

  7. linux(Debian)下安装与MySql的安装、卸载、配置及使用

    参考资料:http://www.cnblogs.com/xusir/p/3334217.html 以下是简要记录. 一.安装 安装:apt-get install mysql-server mysql ...

  8. 生成元(Digit Generator ,ACM/ICPC Seoul 2005 ,UVa 1583)

    生成元:如果 x 加上 x 各个数字之和得到y,则说x是y的生成元. n(1<=n<=100000),求最小生成元,无解输出0. 例如:n=216 , 解是:198 198+1+9+8=2 ...

  9. linux+apache url大小写敏感问题

    Linux对文件目录大小写敏感,URL大小写敏感会导致网页打不开,解决方法之一是启用Apache的mod_speling.so模块. 1.确认/usr/lib/httpd/modules目录下是否存在 ...

  10. mysql 自连接

    SELECT语句中的自连接. 到目前为止,我们连接的都是两张不同的表,那么能不能对一张表进行自我连接呢?答案是肯定的. 有没有必要对一张表进行自我连接呢?答案也是肯定的. 表的别名: 一张表可以自我连 ...