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. webservice配置

    服务端配置:第一步:引用jar包commons-httpclient.jarcommons-logging.jarjdom-10.jarwsdl4j-1.6.1.jarxbean-spring-2.8 ...

  2. 洛谷P1130 红牌

    题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌.获得红牌的过程是相当复杂 ,一共包括N个步骤.每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件.为了加快进程,每一步政府都派了 ...

  3. c++ 函数调用在进入下一个循环的时候会再次初始化参数,将函数体直接写进去就正常

    #include"stdafx.h" #include"string" #include<iostream> #include<vector& ...

  4. linux内存回收 内核参数

    ss -atu| awk '/^tcp/{++S[$2]} END {for(a in S) print a,S[a]}' ps up pid (RSS:实际内存大小,长驻内存) ps o pid,c ...

  5. form的submit与onsubmit的用法与区别

    发生顺序:onsubmit -> submit1.阻止表单提单:<script>function submitFun(){    //逻辑判断    return true; //允 ...

  6. iOS动画中的枚举UIViewAnimationOptions

    若本帖转出“博客园”请注明出处(博客园·小八究):http://www.cnblogs.com/xiaobajiu/p/4084747.html 笔记 首先这个枚举属于UIViewAnimation. ...

  7. python集合类型set

    set 类型的简单粗暴取出并集合交集  |   & li=[11,22,33] n_li=[44,55] b= (list(set(li)&set(n_li))) b2=set(li) ...

  8. 【转】不得不看的两次从C++回归C的高手评论C++

    不得不看的两次从C++回归C的高手评论C++ Linux之父炮轰C++:糟糕程序员的垃圾语言 Linux之父话糙理不糙 不得不看的两次从C++回归C的高手评论C++ C语言是否该扔进垃圾桶 为什么每个 ...

  9. poj1012.Joseph(数学推论)

    Joseph Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 493  Solved: 311 Description The Joseph's prob ...

  10. Inheritance

    Often, classes will have shared characteristics with other classes. Rewriting the same methods for e ...