POJ:3977-Subset(双向搜索)
Subset
Time Limit: 30000MS     Memory Limit: 65536K 
Total Submissions: 5961     Accepted: 1129
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
解题心得:
- 就是一个双向搜索,要求的是选择出来的元素的总和的绝对值最小,按照双向搜索的思路去做就可以了。但是要注意的一点是在二分搜索最相近的答案的时候可能从这个数的lower_bound产生的结果,或者lower_bound的位置-1产生绝对值最小的答案。
#include <algorithm>
#include <cstring>
#include <map>
#include <stdio.h>
using namespace std;
typedef long long ll;
const ll maxn = 45;
const ll MAX = 1e15;
map <ll,ll> M;
pair <ll,ll> ans;
ll n,num[maxn];
ll Abs(ll x) {
    if(x < 0)
        return -x ;
    return x;
}
void init() {
    M.clear();
    ans = make_pair(MAX,MAX);
    for(int i=0;i<n;i++) scanf("%lld",&num[i]);
}
void get_sum(ll mid) {
    ll cnt,sum;
    for(ll i=1;i<(1<<mid);i++) {
        cnt = sum = 0;
        for(ll j=0;j<mid;j++) {
            if(1&(i>>j)) {
                sum += num[j];
                cnt++;
            }
        }
        ans = min(ans,make_pair(Abs(sum),cnt));
        if(M[sum]) {
            M[sum] = min(M[sum],cnt);
        } else
            M[sum] = cnt;
    }
}
void solve(ll mid) {
    map<ll,ll> :: iterator iter;
    for(ll i=1;i<(1<<(n-mid));i++) {
        ll sum,cnt;
        sum = cnt = 0;
        for(int j=0;j<(n-mid);j++) {
            if(1&(i>>j)) {
                sum += num[mid+j];
                cnt++;
            }
        }
        ans = min(ans,make_pair(Abs(sum),cnt));
        iter = M.lower_bound(-sum);
        if(iter != M.end()) {
            ans = min(ans,make_pair(Abs(iter->first+sum),cnt+iter->second));
        }
        if(iter != M.begin()) {
            iter--;
            ans = min(ans,make_pair(Abs(iter->first+sum),iter->second+cnt));
        }
    }
    printf("%lld %lld\n",ans.first,ans.second);
}
int main() {
    while(scanf("%lld",&n) && n) {
        init();
        ll mid = n>>1;
        get_sum(mid);
        solve(mid);
    }
    return 0;
}POJ:3977-Subset(双向搜索)的更多相关文章
- POJ 3977 - subset - 折半枚举
		2017-08-01 21:45:19 writer:pprp 题目: • POJ 3977• 给定n个数,求一个子集(非空)• 使得子集内元素和的绝对值最小• n ≤ 35 AC代码如下:(难点:枚 ... 
- POJ 3977 Subset
		Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 3161 Accepted: 564 Descriptio ... 
- poj 3977 Subset(折半枚举+二进制枚举+二分)
		Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 5721 Accepted: 1083 Descripti ... 
- POJ  3977 Subset(折半枚举+二分)
		SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ... 
- 【折半枚举+二分】POJ 3977 Subset
		题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ... 
- [poj] 3977 Subset || 折半搜索MITM
		原题 给定N个整数组成的数列(N<=35),从中选出一个子集,使得这个子集的所有元素的值的和的绝对值最小,如果有多组数据满足的话,选择子集元素最少的那个. n<=35,所以双向dfs的O( ... 
- POJ 3977 Subset | 折半搜索
		题目: 给出一个整数集合,求出非空子集中元素和绝对值最小是多少(元素个数尽量少) 题解: 分成两半 爆搜每一半,用map维护前一半的值 每搜出后一半的一个值就去map里找和他和绝对值最小的更新答案 # ... 
- POJ - 3977 Subset(二分+折半枚举)
		题意:有一个N(N <= 35)个数的集合,每个数的绝对值小于等于1015,找一个非空子集,使该子集中所有元素的和的绝对值最小,若有多个,则输出个数最小的那个. 分析: 1.将集合中的元素分成两 ... 
- POJ 3977:Subset(折半枚举+二分)
		[题目链接] http://poj.org/problem?id=3977 [题目大意] 在n个数(n<36)中选取一些数,使得其和的绝对值最小. [题解] 因为枚举所有数选或者不选,复杂度太高 ... 
- Subset POJ - 3977(折半枚举+二分查找)
		题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ... 
随机推荐
- 计算Sn
			求Sn=a+aa+aaa+…+aa…aaa(有n个a)之值,其中a是一个数字. 例如:2+22+222+2222+22222(n=5), 输入 输入两个数.第一个为a ,第二个为n(表示有多少个数相加 ... 
- 【起航计划 013】2015 起航计划 Android APIDemo的魔鬼步伐 12 App->Activity->SetWallpaper  设置壁纸  WallpaperManager getDrawingCache使用
			SetWallpaper介绍如何在Android获取当前Wallpaper,对Wallpaper做些修改,然后用修改后的图像重新设置Wallpaper.(即设置>显示>壁纸>壁纸的功 ... 
- C#对bat脚本文件的操作示例
			实现C#操作bat脚本文件 using System;using System.Collections.Generic;using System.ComponentModel;using System ... 
- C++ Eigen库和Matlab对比
			// A simple quickref for Eigen. Add anything that's missing. // Main author: Keir Mierle #include &l ... 
- window下mycat要放在根目录下
			原理文档没有跟我开玩笑呢? 建议放在盘符根目录下 ,无视的我,检查了多遍jdk环境,检查了多遍bat文件内容,仍然没有解决 找不到或无法加载主类 直到我乖乖的把目录放跟盘符才解决,心好累= =! 可能 ... 
- 会说话的ABAP report
			report z. INCLUDE ole2incl. DATA: ole TYPE ole2_object, voice TYPE ole2_object, text ... 
- NYOJ(680),摘枇杷,(暴力,或者二分搜索)
			题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=680 很巧妙的一个题目,就是看你的逆向思维,result 一定是max(a[i])~sum ... 
- Can Microsoft’s exFAT file system bridge the gap between OSes?
			转自:http://arstechnica.com/information-technology/2013/06/review-is-microsofts-new-data-sharing-syste ... 
- Mybatis-generator自动生成
			第一步:导入架包 <build> <plugins> <plugin> <groupId>org.mybatis.generator</group ... 
- [USACO07FEB]银牛派对Silver Cow Party---最短路模板题
			银牛排队 对于我这种蒟蒻来说,还是不要跑一次单元最短路.跑两次好写呀(- ̄▽ ̄)- 而题目中是有向图.如果如果按照题意进行最短路的话.就会出现一个单终点最短路和一个单起点最短路 对于单起点自然就是套模 ... 
