【折半枚举+二分】POJ 3977 Subset
题目内容
Vjudge链接
给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小。
输入格式
输入含多组数据,每组数据有两行,第一行是元素组合\(n\)(若\(n\)为0表示输入结束),第二行有\(n\)个数,表示要给出的\(n\)个数。
数据范围
\(n\le 35\)
输出格式
每组数据输出一行两个数中间用空格隔开,表示最小的绝对值和该子集的元素个数。
样例输入
1
10
3
20 100 -100
0
样例输出
10 1
0 2
思路
在学必修一的第一节课我们就知道有\(n\)个数的集合的非空子集有\(2^n-1\)个,因此此题直接枚举的话大小回到\(2^{35}-1\),显然出题人没有这么好心。
这里用到一种思想叫做对半枚举。可以想到\(2^{17}-1=131071\),比较优秀的,那么就开始对半枚举就好了。将\(n\)的数分为前\(\frac{n}{2}\)和后\(\frac{n}{2}\)进行枚举。同时可以结合二分查找。
如果是一个空集加上一个非空,那么得到的也是非空集合,当然如果两个空集加在一起肯定也还是空集。
注意下边界。
代码
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
ll Abs(ll x){//据说POJ不支持abs函数?
return x > 0 ? x : -x;
}
int n;
ll a[40];
int main(){
while (scanf("%d",&n)&&n!=0){
for (int i=1;i<=n;++i)
scanf("%d",a+i);
map<ll,int> g;//一开始想用结构体结果发现结构体不能用lower_bound
ll ans=Abs(a[1]);
int len=n;
for (int i=1;i<(1<<(n/2));++i){
ll sum=0;
int j=i,cnt=0,pos=1;
while(j&&pos<=n/2){
if (j&1){
sum+=a[pos];
cnt++;
}
j>>= 1;
pos++;
}
if (Abs(sum)<ans){
ans=Abs(sum);
len=cnt;
}
else if(Abs(sum)==ans){
len=min(len, cnt);
}
if(g[sum])
g[sum]=min(g[sum], cnt);
else
g[sum]=cnt;
}
for (int i=1;i<(1<<(n-n/2));++i){
ll sum=0;
int cnt=0,pos=1,j=i;
while (j&&pos+n/2<= n){
if (j&1){
sum+= a[pos+n/2];
cnt++;
}
j>>= 1;
pos++;
}
if(Abs(sum) < ans){
ans=Abs(sum);
len=cnt;
}
else if(Abs(sum)==ans){
len=min(len,cnt);
}
map<ll,int>::iterator it=g.lower_bound(-sum);//迭代器都要忘光了orz
if(it!=g.end()){
if(Abs(sum+it->first)<ans){
ans=Abs(sum+it->first);
len=cnt+it->second;
}
else if(Abs(sum+it->first)==ans){
len=min(len,cnt+it->second);
}
}
if (it!=g.begin()){
it--;
if(Abs(sum+it->first)<ans){
ans=Abs(sum+it->first);
len=cnt+it->second;
}
else if(Abs(sum+it->first)==ans){
len=min(len,cnt+it->second);
}
}
}
scanf("%d %d\n",Abs(ans),len);
}
return 0;
}
代码启发
https://www.jianshu.com/p/27eefa7b990e
膜一下dalao的玛丽
【折半枚举+二分】POJ 3977 Subset的更多相关文章
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- 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 - 折半枚举
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(折半枚举+二分)
[题目链接] 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 ...
- POJ - 3977 Subset(二分+折半枚举)
题意:有一个N(N <= 35)个数的集合,每个数的绝对值小于等于1015,找一个非空子集,使该子集中所有元素的和的绝对值最小,若有多个,则输出个数最小的那个. 分析: 1.将集合中的元素分成两 ...
- POJ 2549 Sumsets(折半枚举+二分)
Sumsets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11946 Accepted: 3299 Descript ...
随机推荐
- HTML全局属性(global attribute)有哪些(包含H5)
1.accesskey:提供了为当前元素生成键盘快捷键的提示.这个属性由空格分隔的字符列表组成.浏览器应该使用在计算机键盘布局上存在的第一个. 2.autocapitalize:控制用户的文本输入是否 ...
- Unit4:碎片
基本使用 动态调用 碎片和活动 碎片周期
- java键对值SHA256加密接口请求
import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.htt ...
- Linux自动同步时间的方法
介绍两种同步linux系统的时间方法: (1) 开启ntpd服务,即配置ntp服务器实现时间同步. (2) 利用ntp客户端程序,即ntpdate同步时间. 注意:因为ntp服务器本来就会与上层时间服 ...
- matplotlib | Python强大的作图工具,让你从此驾驭图表(二)
今天是数据处理专题的第10篇文章,我们继续来聊聊matplot这个工具库. 在上周的文章当中我们介绍了matplot的基本用法,以及展示了一些简单的例子,让大家直观地了解这个工具包.我们可以简单地将它 ...
- vue自适应布局的n中方法
在index.html中 head标签中 <script> //通过window.screen.width获取屏幕的宽度 var offWidth = window.screen.widt ...
- hystrix文档翻译之概述
Hystrix是什么 在一个大型的分布式系统中,难免有些依赖服务会失败.hystrix通过容错逻辑来控制不同服务间的交互.hystrix通过隔离各服务交互节点来防止连级错误,并且提供降级功能,最终保证 ...
- JMeter5.0在windows(含插件安装)
一.jmeter下载 前提:已经安装jdk8+ jmeter下载地址:http://jmeter.apache.org/download_jmeter.cgi 有Binaries和Source版本 前 ...
- 工具请求接口参数为string类型的JSON字符串时需要加转义字符模拟测试
例如postMan传String类型的json字符串请后台接口时,需要\转义
- C++中数组作为形参的方法
转载:https://blog.csdn.net/qq_33374294/article/details/90769668 原链接:https://www.cnblogs.com/abella/p/1 ...