POJ 3977 Subset
| Time Limit: 30000MS | Memory Limit: 65536K | |
| Total Submissions: 3161 | Accepted: 564 |
Description
Input
Output
Sample Input
1
10
3
20 100 -100
0
Sample Output
10 1
0 2
Source
#include <cstdio>
#include <map>
#define ll long long
using namespace std; int n;
ll a[40]; ll ll_abs(ll x)
{
return x >= 0 ? x : -x;
} void solve()
{
map<ll, int> mp;
map<ll, int>::iterator it;
pair<ll, int> res(ll_abs(a[0]), 1); //初始化结果为第一个元素
for(int i = 1; i < 1<<(n/2); ++i){ //枚举区间为[1, 2^n),当i为0时,子集为空
ll sum = 0;
int num = 0;
for(int j = 0; j < n/2; ++j){ //按位枚举
if((i>>j)&1){
sum += a[j];
++num;
}
}
res = min(res, make_pair(ll_abs(sum), num)); //子集的元素只取自于A
it = mp.find(sum);
if(it != mp.end())
it->second = min(it->second, num);
else
mp[sum] = num;
}
for(int i = 1; i < 1<<(n-n/2); ++i){
ll sum = 0;
int num = 0;
for(int j = 0; j < n-n/2; ++j){
if((i>>j)&1){
sum += a[n/2+j];
++num;
}
}
res = min(res, make_pair(ll_abs(sum), num)); //子集的元素只取自于B
it = mp.lower_bound(-sum); //查找与-sum最相近的值
if(it != mp.end()) //可能在该位置
res = min(res, make_pair(ll_abs(it->first+sum), it->second+num));
if(it != mp.begin()){ //可能在该位置的前一个位置
--it;
res = min(res, make_pair(ll_abs(it->first+sum), it->second+num));
}
}
printf("%I64d %d\n", res.first, res.second);
} int main()
{
while(scanf("%d", &n), n){
for(int i = 0; i < n; ++i)
scanf("%I64d", &a[i]);
solve();
}
return 0;
}
POJ 3977 Subset的更多相关文章
- 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: 5721 Accepted: 1083 Descripti ...
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- 【折半枚举+二分】POJ 3977 Subset
题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ...
- [poj] 3977 Subset || 折半搜索MITM
原题 给定N个整数组成的数列(N<=35),从中选出一个子集,使得这个子集的所有元素的值的和的绝对值最小,如果有多组数据满足的话,选择子集元素最少的那个. n<=35,所以双向dfs的O( ...
- POJ 3977 Subset | 折半搜索
题目: 给出一个整数集合,求出非空子集中元素和绝对值最小是多少(元素个数尽量少) 题解: 分成两半 爆搜每一半,用map维护前一半的值 每搜出后一半的一个值就去map里找和他和绝对值最小的更新答案 # ...
- POJ - 3977 Subset(二分+折半枚举)
题意:有一个N(N <= 35)个数的集合,每个数的绝对值小于等于1015,找一个非空子集,使该子集中所有元素的和的绝对值最小,若有多个,则输出个数最小的那个. 分析: 1.将集合中的元素分成两 ...
- 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 1795
DNA Laboratory Time Limit: 5000MS Memory Limit: 30000K Total Submissions: 1425 Accepted: 280 Des ...
- Asp.net 身份验证
Forms 验证方式对基于用户的验证授权提供了很好的支持,可以通过一个登录页面验证用户的身份,将此用户的身份发回到客户端的Cookie,之后此用户再访问这个 web应用就会连同这个身份Cookie一起 ...
- hdu 3923 Invoker
完全是套用polya模版…… ;}
- 李洪强iOS开发支付集成之银联支付
iOS开发支付集成之银联支付 银联官网在这里,这里能下载SDK或者是看文档.最新的版本写的简单了很多,看文档一直做下去基本上就没问题了. 首先,SDK在这里下载,里面包含需要的库文件和详细的文档. 银 ...
- 一个不错的log4j.properties例子
# Set root logger level to WARN and append to stdout #在开发环境下日志级别要设置成DEBUG,生产环境设置成info或error log4j.ro ...
- NSDictionary 键值对查找
NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys: @"1",@"a", ...
- linux 查看某一端口的占用情况
查看某一端口的占用情况: lsof -i:端口号,例如查看端口21是否被占用 lsof -i: 实例:查看端口是否被占用,如果被占用结束掉该端口 [root@localhost splunk]# ls ...
- 【问题】和NULL比较遇到的问题
1.问题描述: select FName from teacher where FId not in( select distinct FTeacherId from student ) 子查询返回的 ...
- PHP程序员最常犯的11个MySQL错误
对于大多数web应用来说,数据库都是一个十分基础性的部分.如果你在使用PHP,那么你很可能也在使用MySQL—LAMP系列中举足轻重的一份子. 对于很多新手们来说,使用PHP可以在短短几个小时之内轻松 ...
- Java中ArrayList和LinkedList区别
ArrayList和LinkedList的大致区别如下:1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayLis ...