POJ 3977 解题报告

Subset

Time Limit: 30000MS   Memory Limit: 65536K
Total Submissions: 6499   Accepted: 1227

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

 

题目的意思 你可以取非空集合 任意组合 看看能不能绝对值最小 也就是越接近0

我们怎么看这题 我们先想 这有35个东西

又是组合 很容易想到二进制枚举 但是2^35太大了 

那么我们又为了能做题 想到2^17是个比较好的范围

那么我们就可以对半枚举了

把前n/2个和后n/2个分开 进行枚举

从i=0到(1<

因为我们可以是一个空集 加 一个非空集 组合 也是一个非空集合

那我们马上发现 两个空集合加起来肯定是空集合

所以如果枚举的两个集合都是空集 那么得到的也是空集

所以我们可以进行二进制枚举了

前面写了一发 不知道为啥WA 目前还不知道

重新写了就过了。。。

lower_bound不能直接对结构体 所以开一个新数组

并且在找到的xb左右范围进行二分 防止迷之二分

注意判断下边界条件

 

/*
POJ 3977
*/
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
#define dbg(x) ;
ll arr[45];
ll ans_new[1<<18];
ll ABS(ll a){
   if(a>=0) return a;
   return -a;
}
struct node {
  ll sum;
  int num;
  bool operator < (const node other) const
  {
  if(sum==other.sum) return num < other.num;
  return sum=(1<ABS(ans_new[j]+ans_l[i].sum)){
                maxx = ABS(ans_new[j]+ans_l[i].sum);
                num = ans_r[j].num+ans_l[i].num;
                dbg(ans_r[j].num);
                dbg(ans_l[i].num);
                dbg(ans_new[j]);
                dbg(ans_l[i].sum);
                dbg(num);
                dbg(maxx);
            }
            else if(maxx == ABS(ans_new[j]+ans_l[i].sum)){
                if(num> ans_r[j].num+ans_l[i].num) num = ans_r[j].num+ ans_l[i].num;
            }
        }
      }
      printf("%lld %d\n",maxx,num);
   }

   return 0;
}

 

你可能感兴趣的:(ACM,二分查找)