2017-08-26 11:38:42

writer:pprp

已经是第二次写这个题了,但是还是出了很多毛病

先给出AC代码:

解题思路:

之前在培训的时候只是笼统的讲了讲怎么做,进行二分对其中一边进行暴力枚举,对另一边用lower_bound查找算出的相反数

现在给出详细一点的思路:

答案可能在左边枚举的部分,也可能在右边枚举的部分,也可能在两边加起来的和中

所以从这三个方面不能少考虑;

还有用到了map所以算出来的key是唯一的,所以当算出来两个key相等的时候,应该采用value也就是cnt比较小的那个数

细节比较多,很容易就wa

  1. /*
  2. @prama: poj 3977
  3. @writer:pprp
  4. @declare:暴力+二分
  5. @date:2017/8/26
  6. */
  7.  
  8. #include <iostream>
  9. #include <cstring>
  10. #include <cstdio>
  11. #include <cstdlib>
  12. #include <cstring>
  13. #include <algorithm>
  14. #include <cmath>
  15. #include <map>
  16. #define ll long long
  17. #define IOS ios::sync_with_stdio(false),cin.tie(0);
  18. #define tag cout <<"-------" << endl;
  19.  
  20. using namespace std;
  21. int N;
  22. const int maxn = ;
  23. ll subset[maxn]; //改成ll
  24.  
  25. ll ll_abs(ll a)
  26. {
  27. return a > ? a:- a;
  28. }
  29.  
  30. int main()
  31. {
  32. IOS;
  33. while(cin >> N && N)
  34. {
  35. memset(subset,,sizeof(subset));
  36. for(int i = ; i < N ; i++)
  37. cin >> subset[i];
  38.  
  39. //初始化这个pair,用来记录答案
  40. pair<ll,int> ans(ll_abs(subset[]),);
  41. map<ll,int> mp;// sum -> cnt
  42.  
  43. //二进制枚举前一半
  44. for(int i = ; i < ( << N/) ; i++)
  45. {
  46. ll sum = ;
  47. int cnt = ;
  48. for(int j = ; j < N/ ; j++)
  49. {
  50. //二进制枚举,判断第j为是否被选中
  51. if((i >> j)&)
  52. {
  53. sum += subset[j];
  54. cnt++;
  55. }
  56. }
  57. //**增加一个判断,如果一个都没有被选中
  58. if(cnt == ) continue;
  59.  
  60. //对结果进行操作,找到当前最小的sum
  61. ans = min(ans, make_pair(ll_abs(sum),cnt));
  62.  
  63. //将每次枚举的情况都加入map中去
  64. map<ll,int>::iterator ii = mp.find(sum);
  65. if(ii != mp.end())//如果能找到,就采用那个比较小的cnt,因为map的key是unique的所以要进行如下判断
  66. ii->second = min(ii->second,cnt);
  67. else //如果没有找到就直接放到map中去
  68. mp[sum] = cnt;
  69. }
  70.  
  71. //对后一半进行枚举,得到的sum可从map中寻找最接近-sum的值
  72. for(int i = ; i < ( << (N - N/)); i++)
  73. {
  74. ll sum = ;
  75. int cnt = ;
  76. for(int j = ; j < (N - N/); j++)
  77. {
  78. if((i >> j) & )
  79. {
  80. cnt++;
  81. sum += subset[N/ +j];
  82. }
  83. }
  84. //**增加一个判断,如果一个都没有被选中
  85. if(cnt == ) continue;
  86. //对结果进行操作,找到当前最小的sum
  87. ans = min(ans, make_pair(ll_abs(sum),cnt));
  88.  
  89. //对后半段进行找最接近于-sum的值
  90. //运用lower_bound查找的是不小于-sum的值,就是比-sum略大的值
  91. map<ll,int>::iterator it = mp.lower_bound(-sum);
  92. if(it != mp.end())//如果可以找到就进行比较
  93. {
  94. ans = min(ans, make_pair(ll_abs(it->first + sum),it->second+cnt));
  95. }
  96.  
  97. // 有可能是比-sum略小的值,这个也可以用upper_bound来写 ??
  98. if(it != mp.begin())
  99. {
  100. it--;
  101. ans = min(ans, make_pair(ll_abs(it->first + sum),it->second+cnt));
  102. }
  103. //经过测试,不可以采用这个方法
  104. map<ll,int>::iterator tt = mp.upper_bound(-sum);
  105. {
  106. ans = min(ans, make_pair(ll_abs(it->first + sum),it->second+cnt));
  107. }
  108. }
  109.  
  110. cout << ans.first << " " << ans.second << endl;
  111. }
  112. return ;
  113. }

遇到的问题:

1、数据类型的选择,数据范围是10^15 远远超过int类型了,所以一开始没有检查数组类型,导致wa了很多次,

也浪费了很长时间。

2、lower_bound和upper_bound的用法还是不是很清楚。

最后那部分不可以用upper_bound直接将指针进行移动就可以

poj3977 - subset - the second time - 暴力 + 二分的更多相关文章

  1. 8VC Venture Cup 2016 - Elimination Round E. Simple Skewness 暴力+二分

    E. Simple Skewness 题目连接: http://www.codeforces.com/contest/626/problem/E Description Define the simp ...

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

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

  3. Codeforces Round #367 (Div. 2) A B C 暴力 二分 dp(字符串的反转)

    A. Beru-taxi time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  4. Subsequence(暴力+二分)

    Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10875   Accepted: 4493 Desc ...

  5. Vijos P1116 一元三次方程求解【多解,暴力,二分】

    一元三次方程求解 描述 有形如:ax^3+bx^2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之 ...

  6. I Count Two Three HDU - 5878(暴力二分)

    为甚么16年Qingdao Online 都是暴力题emm///... 先暴力预处理 然后lower _bound二分 #include <iostream> #include <c ...

  7. HDU6127 简单几何 暴力二分

    LINK 题意:给出n个点,每个点有个权值,可以和任意另外一点构成线段,值为权值积.现问过原点的直线中交所有线段的权值和的最大值,注意直线必不经过点. 思路:直线可以将点集分为两侧,此时的权值为两侧点 ...

  8. Codeforces Beta Round #3 B. Lorry 暴力 二分

    B. Lorry 题目连接: http://www.codeforces.com/contest/3/problem/B Description A group of tourists is goin ...

  9. Codeforces Round #345 (Div. 2) D. Image Preview 暴力 二分

    D. Image Preview 题目连接: http://www.codeforces.com/contest/651/problem/D Description Vasya's telephone ...

随机推荐

  1. XAF 如何从Excel复制多个单元格内容到GridView(收藏)

    XAF 如何从Excel复制多个单元格内容到GridView 2012年04月11日 ⁄ 综合 ⁄ 共 10998字 ⁄ 字号 小 中 大 ⁄ 评论关闭 how to paste some excel ...

  2. Django 框架搭建入门案例

    1. 什么是 web 框架 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端; # 示例: import socket def handle_re ...

  3. Unity系统自带函数生命周期以及相互关系

    官方参考手册:http://docs.unity3d.com/Manual/ExecutionOrder.html unity脚本从唤醒到销毁都有着一套比较完善的生命周期,添加任何脚本都要遵守生命周期 ...

  4. 怎样将Arranged_2压入General_Polygon_set_2中

    Thursday, March 14, 2013 How to Jam an Arrangement_2 into a General_polygon_set_2 I spent about thre ...

  5. UVA+POJ中大数实现的题目,持续更新(JAVA实现)

    UVA10494:If We Were a Child Again 大数除法加取余 import java.util.Arrays; import java.util.Scanner; import ...

  6. 模块讲解----sys

    sys:跟python解释器相关的信息 #命令行参数list,第一个元素时程序本身路径 print(sys.argv) 注意:执行脚本时,可以传参数. #退出程序,正常退出时exit(0) sys.e ...

  7. maven tomcat7-maven-plugin配置及背景

    背景: 在研发阶段,想让一个服务通过tomcat启动起来有很多的方法,常用的idea都有这样的支持,那么如果我们没有tomcat,能不能让服务通过tomcat启动起来呢?maven就提供了这样的支持. ...

  8. iClap助力移动互联网企业实现规范化管理

    移动互联网的迅速崛起,智能移动客户端深刻而全面地影响着人类生活与工作习惯.而企业办公已从原始的纸张办公,到固定PC办公,跨入到一个应用范围更广.效率更高的移动办公时代.由静生动,让企业办公更加人性化和 ...

  9. spoj1811 LCS - Longest Common Substring

    地址:http://www.spoj.com/problems/LCS/ 题面: LCS - Longest Common Substring no tags  A string is finite ...

  10. VS插件神器 ReShaper入门

    @简介: 1,Resharper提供以下6个核心功能,分别是: (1). 代码分析(Code Analysis):智能提示代码中存在的问题和修复建议. (2). 编码助手(Coding Assista ...