题意:

给一串数字,选取其中的数字,使其值最小,并且选取数字的个数尽可能少.

分析:

因为数字范围很大,因此不能使用动态规划来计算,从而考虑折半枚举来进行计算。

将这串数字划分为两部分,第一部分用字典序枚举的方式输出所有的可能结果,将结果输入数组,再对数组进行升序。

再对该串数字的另一部分,进行字典序枚举,对于每一种可能性,在第一个数组中对这种可能性的负数进行二分查找,并与ans进行比较。

【本题在各种区间细节中有些麻烦,需要注意,详情见代码】

代码:

#include <cstdio>
#include <iostream>
#include <queue>
#include <algorithm>
#define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
typedef long long ll;
const ll SIZE = 1<<18;int n,ans_num;
ll a[40];
ll ans;struct TMP1{ll v;int id;
}tmp1[SIZE];bool operator < (TMP1 x,TMP1 y){if(x.v!=y.v)return x.v<y.v;elsereturn x.id<y.id;
}ll abss(ll x){if(x < 0) x = (-1)*x;return x;
}int main()
{while(~scanf("%d",&n),n){rep(i,1,n){scanf("%lld",&a[i]);}ans_num = 0;ans = 1e17;int k = 0;//用字典序枚举出1-n/2物品的所有取用方式rep(i,1,(1<<(n/2))-1){ll tmpv = 0;int tmpn = 0;rep(j,0,n/2-1){int x = (i>>j)&1;if(x){tmpv += a[n/2 - j];tmpn++;}}++k;tmp1[k].v = tmpv;tmp1[k].id = tmpn;if(ans > abss(tmpv)){ans = abss(tmpv);ans_num = tmpn;}else if(ans == abss(tmpv) && ans_num > tmpn) ans_num = tmpn;}//删去无用元素sort(tmp1+1,tmp1+1+k);int m1 = 1;rep(i,2,k){if(tmp1[m1].v != tmp1[i].v){++m1;tmp1[m1].v = tmp1[i].v;tmp1[m1].id = tmp1[i].id;}}//枚举另外一边的元素rep(i,1,(1<<(n-n/2))-1){ll tmpv = 0;int tmpn = 0;rep(j,0,n-n/2-1){int x = (i>>j)&1;if(x){tmpv += a[j+n/2+1];tmpn++;}}TMP1 tp;tp.v = (-1)*tmpv;tp.id = tmpn;if(ans > abss(tmpv)){ans = abss(tmpv);ans_num = tmpn;}else if(ans == abss(tmpv) && ans_num > tmpn) ans_num = tmpn;int kk1 = lower_bound(tmp1+1,tmp1+m1+1,tp)-tmp1;if(kk1 <= 0) kk1 = 1;if(kk1 > m1) kk1 = m1;if(abss(tmpv+tmp1[kk1].v)<ans){ans = abss(tmpv+tmp1[kk1].v);ans_num = tmpn+tmp1[kk1].id;}else if(abss(tmpv+tmp1[kk1].v) == ans && (tmpn+tmp1[kk1].id) < ans_num)ans_num = tmpn+tmp1[kk1].id;//有一点是debug长达3h的关键错误//lower_bound是返回 >= 的值//upper_bound是返回 > 的值//千万不要以为lower_bound是返回 <= !!!!!!!!!int kk2;if(kk1 > 1) kk2 = kk1-1;else continue;if(abss(tmpv+tmp1[kk2].v)<ans){ans = abss(tmpv+tmp1[kk2].v);ans_num = tmpn+tmp1[kk2].id;}else if(abss(tmpv+tmp1[kk2].v) == ans && (tmpn+tmp1[kk2].id) < ans_num)ans_num = tmpn+tmp1[kk2].id;}printf("%lld %d\n",ans,ans_num);
}return 0;
}

【POJ 3977】【折半枚举】【超大背包】Subset【暑期 No.7】相关推荐

  1. Subset POJ - 3977(折半枚举+二分+二进制枚举)

    题意: 给你一个集合N(N<=35),问集合的子集,除了空集,使得自己中所有元素和的绝对值最小,若存在多个值,那么选择子集中元素最少的那个. 题目: Given a list of N inte ...

  2. POJ 3373 模运算 + 折半枚举

    题意 传送门 POJ 3373 题解 置换 nnn 部分数位上的数字得到 mmm,其能被 kkk 整除,且置换数位最少,有多个 mmm 满足上述条件则求最小值. 考虑到 k≤104k\leq 10^4 ...

  3. P4799-世界冰球锦标赛(折半枚举模板)

    题目 1<=n<=40,1<=m<=1e18; 输入样例#1: 5 1000 100 1500 500 500 1000 输出样例#1: 8 01背包,m范围小的话可以使用.这 ...

  4. 2017西安交大ACM小学期 刁钻的顾客[3进制+折半枚举]

    刁钻的顾客 发布时间: 2017年7月3日 10:23   时间限制: 3000ms   内存限制: 128M 描述 XJTU校园内新开一家商店,可是来了一位刁钻的顾客要购买商品A和商品B.关于商品的 ...

  5. poj_3977 折半枚举

    题目大意 给定N(N<=35)个数字,每个数字都<= 2^15. 其中一个或多个数字加和可以得到s,求出s的绝对值的最小值,并给出当s取绝对值最小值时,需要加和的数字的个数. 题目分析 需 ...

  6. CodeForces888E Maximum Subsequence(折半枚举+two-pointers)

    题意 给定一个包含\(n\)个数的序列\(a\),在其中任选若干个数,使得他们的和对\(m\)取模后最大.(\(n\leq 35\)) 题解 显然,\(2^n\)的暴枚是不现实的...,于是我们想到了 ...

  7. zstu新生赛 Problem A: Baby Coins(折半枚举+二分)

    Problem A: Baby Coins Time Limit: 1 Sec Memory Limit: 128 MB Submit: 274 Solved: 29 Description Baby ...

  8. XMUOJ·小H的超大背包

    小H的超大背包 题目描述 小H有一个容量特别大的背包,用来装一些体积很大的物品. 每个物品都有一个价值,并且只有一件 请你帮助小H计算这个超大背包最大能装多少价值的物品,并且这些物品的总体积不超过背包 ...

  9. 【HDU 5936 --- Difference】折半枚举+二分

    [HDU 5936 --- Difference]折半枚举+二分 Description Little Ruins is playing a number game, first he chooses ...

  10. 【POJ - 2785】4 Values whose Sum is 0 (二分,折半枚举)

    题干: The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, com ...

最新文章

  1. mysql中的merge into,SQL Server 2008中利用merge into关键实现insert/update自动匹配(类似于MySQL中的For Update关键字)...
  2. java托盘图标变白在linux,为什么用java实现windows系统托盘图标总是不显示出来
  3. RabbitMQ 的概念
  4. combineLatest 使用的一个陷阱和基于 debounceTime 的解决方案
  5. 怎么调试内存溢出的c++代码_【C/C++】内存对齐 到底怎么回事?
  6. CyclicBarrier-同步辅助类
  7. oracle的hr工资待遇,oracle的hr用户里employees表
  8. Spring+Struts集成(方案一)
  9. nova.api.openstack.auth解析(ocata版本)
  10. js 移动端的表情包
  11. 酷站60个漂亮可用的外文站点欣赏(经典推荐)
  12. What's new in Xcode 8
  13. C#注册机与绑定软件(转发自:韩兆新的博客园的C#学习笔记——软件注册与注册机)...
  14. NetSuite Account Register报表详解
  15. MacBook Pro 2018电池鼓包、键盘问题免费换新
  16. 安卓平板体验Java开发,还能白嫖一年阿里无影云,真香!(内含白嫖方法,人人可领)...
  17. Ubuntu环境中英文切换
  18. 分析器错误信息:nbsp;无法识别的配置节…
  19. 串口传输速率为9600bps意味着每分钟最多可传送多少个ASCII码字符
  20. 求助 opencv视频播放速度变慢

热门文章

  1. Android 虚拟机快捷键
  2. VS2010 配置PCL1.6.0AII in one 无法启动程序ALL_BUILD
  3. java中foreach怎么访问_JAVA中的foreach怎么用
  4. 自定义控件设置宽度_自定义View开篇,必须跨过的一道坎儿
  5. resetlog oracle,用RMAN的全备恢复resetlog之前的数据
  6. Python(二):基本数据类型、序列的基本操作
  7. STL map 的基本成员函数
  8. 计算机二级与c语言有什么关系,计算机二级c和c++区别?
  9. 基于时间片的高优先级调度_CFS调度器(1)-基本原理
  10. linux静态网络带宽分配策略,Xen网络带宽分配优化方案的设计与实现