POJ-3977-折半枚举,二分
来源:互联网 发布:java中的getclass方法 编辑:程序博客网 时间:2024/05/29 11:09
题目大意:有n个数,要求它的一个子集,使得这个子集的和的绝对值最小,如果有多种情况,选个数最少的那种;
题目解析:直接暴力枚举肯定超时,所以先枚举一半,另一半在枚举的过程中可以二分前一半;
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<map>using namespace std;typedef long long ll;int n;ll a[50];ll Abs(ll x){ if(x<0) return -x; return x;}int main(){ while(scanf("%d",&n)!=EOF&&n) { map<ll,int>m; map<ll,int>::iterator it; for(int i=0;i<n;i++) { scanf("%lld",&a[i]); } pair<ll,int>ans(Abs(a[0]),1); for(int i=1;i<(1<<(n/2));i++) { ll sum=0; int cnt=0; for(int j=0;j<n/2;j++) { if(i&(1<<j)) { sum+=a[j]; cnt++; } } ans=min(ans,make_pair(Abs(sum),cnt)); if(m[sum]) m[sum]=min(m[sum],cnt); else m[sum]=cnt; } for(int i=1;i<(1<<(n-n/2));i++) { ll sum=0; int cnt=0; for(int j=0;j<(n-n/2);j++) { if(i&(1<<j)) { sum+=a[j+n/2]; cnt++; } } ans=min(ans,make_pair(Abs(sum),cnt)); it=m.lower_bound(-sum); if(it!=m.end()) { ans=min(ans,make_pair(Abs(sum+it->first),cnt+it->second)); } if(it!=m.begin()) { it--; ans=min(ans,make_pair(Abs(sum+it->first),cnt+it->second)); } } printf("%lld %d\n",ans.first,ans.second); } return 0;}
0 0
- POJ-3977-折半枚举,二分
- poj 3977 折半枚举+二进制枚举+二分
- 【折半枚举 && 二分】POJ
- poj 3977 折半枚举二分搜索
- POJ 3977 Subset (折半枚举+二分)
- POJ 3977 Subset(折半枚举 + 二分查找)
- poj 3977 Subset 折半枚举
- POJ - 3977 Subset(折半枚举)
- POJ 3977 Subset (折半枚举)
- Poj 3977 Subset 折半枚举 超大背包
- POJ 3977 Subset (简单折半枚举)
- POJ 2785 折半枚举
- poj2785(二分折半枚举)
- codeforces888e(折半枚举+二分搜索)
- poj 3977 Subset 枚举+二分
- POJ 3977(枚举+二分)
- POJ 2549 Sumsets(折半枚举)
- POJ - 2549 Sumsets(折半枚举)
- 在eclipse中用maven创建web项目
- 颜色分类
- java内存分配
- 2014-Network In Network
- struts2通配符及Action开发的三种方式
- POJ-3977-折半枚举,二分
- Thread 的stop方法过时Thread already start解决方法
- 解决RabbitMQ发送数据为空字符串
- 【数值计算】数值解析--联立一次方程组:迭代法
- DB2在Windows和Linux的安装
- printf()用法及介绍
- 二维码
- leetcode 504. Base 7
- The first girlfriend -- AngularJS