POJ3977Subset(折半枚举)
来源:互联网 发布:人体工学椅有用吗 知乎 编辑:程序博客网 时间:2024/06/11 16:56
链接:
http://poj.org/problem?id=3977
题意:
给你n个数,n最大35,让你从中选几个数,不能选0个,使它们和的绝对值最小
如果有一样的,取个数最小的
题解:
先枚举前一半的所有情况 用map记录下来,
然后再枚举后一半的所有情况,再在前一半记录的map里面找相加的和 与0最接近的
不过map居然也可以用lower_bound!
#include <map>#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;#define pli pair<ll, int>map<ll, int> mp;ll a[40];ll labs(ll x){ return x >= 0 ? x : -x;}int main(){ int n; while(cin >> n, n) { mp.clear(); for(int i = 0; i < n; i++) cin >> a[i]; int n1 = n / 2, n2 = n - n1; pli ans = pli(1e18, 0); for(int i = 1; i < (1<<n1); i++) { ll sum = 0;int num = 0; for(int j = 0; j < n1; j++) if(i&(1<<j)) sum += a[j], num++; if(!mp[sum] || num < mp[sum]) mp[sum] = num; pli t = pli(labs(sum), num); if(t < ans) ans = t; } for(int i = 1; i < (1<<n2); i++) { ll sum = 0;int num = 0; for(int j = 0; j < n2; j++) if(i&(1<<j)) sum += a[n1+j], num++; pli t = pli(labs(sum), num); if(t < ans) ans = t; map<ll, int>::iterator k = mp.lower_bound(-sum); if(k != mp.end()) { t = pli(labs((*k).first + sum), num + (*k).second); if(t < ans) ans = t; } if(k != mp.begin()) --k; if(k != mp.end()) { t = pli(labs((*k).first + sum), num + (*k).second); if(t < ans) ans = t; } } cout << ans.first << " " << ans.second << endl; } return 0;}
阅读全文
0 0
- poj3977Subset (折半枚举)
- POJ3977Subset(折半枚举)
- 【折半枚举】
- 折半枚举
- 折半枚举
- 折半枚举--poj2785
- 折半枚举--poj3977
- poj2785(折半枚举)
- POJ3977 Subset 折半枚举
- POJ2549 Sumsets 折半枚举
- poj2549 Sumsets(折半枚举)
- poj2785 折半枚举
- POJ 2785 折半枚举
- poj2549折半枚举
- poj2785(折半枚举)
- poj2549(折半枚举)
- POJ2785 (折半枚举)
- poj3977 Subset 折半枚举
- 在代码中,动态修改图片颜色
- 5.bootstrap入门
- memcache安装配置问题
- C#之接口
- Python装饰器入门详解
- POJ3977Subset(折半枚举)
- DUBBO配置方式
- C++利用链栈实现中缀表达式转换后缀表达式
- java九九乘法表
- java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__aeabi_memclr8" referenced by
- android6.0的权限管理
- PHP攻击网站防御代码-以及攻击代码反译
- BZOJ 2809(优先队列+启发式合并)
- 结构型-装饰者模式(decorator)