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. 15.Android中LinearLayout布局一些小记录

    在App中,我们经常看到布局中会有分割线,直接上代码: <?xml version="1.0" encoding="utf-8"?> <Lin ...

  2. Spring的辅助类

    http://www.cnblogs.com/maoan/p/3446224.html spring获取ApplicationContext对象的方法——ApplicationContextAware

  3. XCode新建Class时自动加前缀(class prefix 修改前缀)

    已经建好的工程,怎么修改class prefix.如图,怎么修改下面的前缀LP,我想改为其他的,比如SH 解决方法: 1.点开Xcode右侧Utilities,Project Document-> ...

  4. Bootstrap教程:[4]栅格系统详解

    http://jingyan.baidu.com/article/6f2f55a1852aa1b5b83e6c5a.html 们都知道bootstrap3.0使用了四种栅格选项来形成栅格系统,这四种选 ...

  5. MyEclipse------带进度条的输入流

    other.jsp <%@ page language="java" import="java.util.*" pageEncoding="UT ...

  6. sleep()

    经常看到线程中用sleep(),到底是什么用处,下面讲的比较通俗: 我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: ...

  7. hdu 2111 Saving HDU

    解题思路: 首先做本题,要清楚题意的要求. 1.读取数据到结构体数组中,然后按其价值降序(价值最大的放在最上面). 2.比较给定的M (包裹容量),如果大于当前宝物的体积,则计算总价值+= 宝物的总价 ...

  8. 用css3制作旋转加载动画的几种方法

    以WebKit为核心的浏览器,例如Safari和Chrome,对html5有着很好的支持,在移动平台中这两个浏览器对应的就是IOS和Android.最近在开发一个移动平台的web app,那么就有机会 ...

  9. 一个令人蛋疼的 Microsoft.AspNet.FriendlyUrls

    我一个项目都基本上做完了,结果部署到我服务器的时候结果一直报404 找不到 一看global.asax有个路由注册的代码 public static void RegisterRoutes(Route ...

  10. Bootstrap新手学习笔记——css

    Css模块: 1.网格系统: class前缀:.col-xs-*,.col-sm-*,.col-md-*,.col-lg-* <div class="container"&g ...