题目链接:http://poj.org/problem?id=3977

给你n个数,找到一个子集,使得这个子集的和的绝对值是最小的,如果有多种情况,输出子集个数最少的;

n<=35,|a[i]|<=10e15

子集个数共有2^n个,所以不能全部枚举,但是可以分为两部分枚举;

枚举一半的所有情况,然后后一半二分即可;

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<string.h>
  4. #include<stdio.h>
  5. #include<math.h>
  6. #include<vector>
  7. #include<map>
  8. using namespace std;
  9. #define N 45
  10. #define PI 4*atan(1.0)
  11. #define mod 1000000007
  12. #define met(a, b) memset(a, b, sizeof(a))
  13. #define INF 10000000000000000
  14. typedef long long LL;
  15.  
  16. int n;
  17. LL a[N];
  18.  
  19. LL Abs(LL x)
  20. {
  21. return x<?-x:x;
  22. }
  23.  
  24. int main()
  25. {
  26. while(scanf("%d", &n), n)
  27. {
  28. for(int i=; i<n; i++)
  29. scanf("%I64d", &a[i]);
  30.  
  31. map<LL, int> M;
  32. map<LL, int>::iterator it;
  33. pair<LL, int> ans(Abs(a[]), );
  34.  
  35. for(int i=; i<<<(n/); i++)
  36. {
  37. LL sum = ;int cnt = ;
  38. for(int j=; j<(n/); j++)
  39. {
  40. if((i>>j)&)
  41. {
  42. sum += a[j];
  43. cnt ++;
  44. }
  45. }
  46. ans = min(ans, make_pair(Abs(sum), cnt));///全部是前半部分的;
  47. if(M[sum])///更新cnt为小的;
  48. M[sum] = min(M[sum], cnt);
  49. else
  50. M[sum] = cnt;
  51. }
  52.  
  53. for(int i=; i<<<(n-n/); i++)
  54. {
  55. LL sum = ;int cnt = ;
  56. for(int j=; j<(n-n/); j++)
  57. {
  58. if((i>>j)&)
  59. {
  60. sum += a[j+n/];
  61. cnt ++;
  62. }
  63. }
  64. ans = min(ans, make_pair(Abs(sum), cnt));///全部是后半部分的;
  65.  
  66. it = M.lower_bound(-sum);///找到第一个大于-sum的位置,然后取两种情况的最小值;
  67.  
  68. if(it != M.end())
  69. ans = min(ans, make_pair(Abs(sum+it->first), cnt+it->second));
  70. if(it != M.begin())
  71. {
  72. it--;
  73. ans = min(ans, make_pair(Abs(sum+it->first), cnt+it->second));
  74. }
  75. }
  76. printf("%I64d %d\n", ans.first, ans.second);
  77. }
  78. return ;
  79. }

Subset---poj3977(折半枚举+二分查找)的更多相关文章

  1. CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。

    1514: Packs Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 61  Solved: 4[Submit][Status][Web Board] ...

  2. poj3977(折半枚举+二分查找)

    题目链接:https://vjudge.net/problem/POJ-3977 题意:给一个大小<=35的集合,找一个非空子集合,使得子集合元素和的绝对值最小,如果有多个这样的集合,找元素个数 ...

  3. Subset POJ - 3977(折半枚举+二分查找)

    题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ...

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

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

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

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

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

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

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

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

  8. POJ 2549 Sumsets(折半枚举+二分)

    Sumsets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11946   Accepted: 3299 Descript ...

  9. SPOJ11469 Subset(折半枚举)

    题意 给定一个集合,有多少个非空子集,能划分成和相等的两份.\(n\leq 20\) 题解 看到这个题,首先能想到的是\(3^n\)的暴力枚举,枚举当前元素是放入左边还是放入右边或者根本不放,但是显然 ...

随机推荐

  1. 苹果应用商店DNS修改加快下载速度

    具体方法:依次点击进入[设置]→[无线局域网]→[WiFi网络右侧小i图标]→更改DNS地址,可以按照自身需求选择以下某个DNS进行更换. OpenDNS:208.67.222.222和208.67. ...

  2. 调用WebServiceWebService提示The maximum string content length quota (8192) has been exceeded while reading XML data的解决办法

    在web.config中,bindings节点下,对应的服务名称中,原本可能是自动折叠的“/>”,需要改成手动折叠的</binding>,然后在中间加上<readerQuota ...

  3. windows phone 7 中怎样定义和使用资源(Resource)

    1. 系统资源. 在wp7开发中可以看到很多使用系统资源(resource)的例子,例如默认的新page: http://blog.csdn.net/matrixcl/article/details/ ...

  4. HDU 4648 Magic Pen 6

    题目链接 6Y什么水平.. #include <cstdio> #include <cstring> #include <string> #include < ...

  5. iOS开发之正则表达式

    正则表达式用于字符串处理.表单验证等场合,实用高效.现将一些常用的表达式收集于此,以备不时之需. 匹配中文字符的正则表达式: [\u4e00-\u9fa5]评注:匹配中文还真是个头疼的事,有了这个表达 ...

  6. Use auto keyword in C++11

    Now compile your program with g++ -std=c++ your_file.cpp -o main

  7. QComboBox 和 QSpinBox 使用方法

    Qt中QComboBox 和 QSpinBox 是两个很常用的空间,QComboBox 是下拉菜单,而 QSpinBox 是调参数的神器,所以它们的用法十分必要熟练掌握. 首先来看 QComboBox ...

  8. jQuery 事件的命名空间

    在没有看到这篇 文章之前,我一直不知道原来bind也可以有命名空间.事实上,我看完这篇文章后,再去翻了一下手册,也才发现了一点点的注释.但手册也仅仅是一句话就带 过去了.没有过多的深究,或许他认为命名 ...

  9. java的包装类(转)

    Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数 ...

  10. Hibernate validation 注解 springmvc 验证 分组

    SpringMVC验证框架Validation特殊用法   1. 分组 有的时候,我们对一个实体类需要有多中验证方式,在不同的情况下使用不同验证方式,比如说对于一个实体类来的id来说,保存的时候是不需 ...