博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 3977 折半枚举
阅读量:6232 次
发布时间:2019-06-21

本文共 1891 字,大约阅读时间需要 6 分钟。

链接:

题意:

给你n个数,n最大35,让你从中选几个数,不能选0个,使它们和的绝对值最小,如果有一样的,取个数最小的 

思路:

子集个数共有2^n个,所以不能全部枚举,但是可以分为两部分枚举;枚举一半的所有情况,然后后一半二分即可;

代码:

 

1 #include"bits/stdc++.h" 2 #define N 45 3 using namespace std; 4 typedef long long LL; 5  6 int n; 7 LL a[N]; 8  9 LL Abs(LL x)10 {11     return x<0?-x:x;12 }13 14 int main()15 {16     while(scanf("%d", &n), n)17     {18         for(int i=0; i
M;22 map
::iterator it;23 pair
ans(Abs(a[0]), 1);24 25 for(int i=1; i<1<<(n/2); i++)26 {27 LL sum = 0;int cnt = 0;28 for(int j=0; j<(n/2); j++)29 {30 if((i>>j)&1)31 {32 sum += a[j];33 cnt ++;34 }35 }36 ans = min(ans, make_pair(Abs(sum), cnt));///全部是前半部分的;37 if(M[sum])///更新cnt为小的;38 M[sum] = min(M[sum], cnt);39 else40 M[sum] = cnt;41 }42 43 for(int i=1; i<1<<(n-n/2); i++)44 {45 LL sum = 0;int cnt = 0;46 for(int j=0; j<(n-n/2); j++)47 {48 if((i>>j)&1)49 {50 sum += a[j+n/2];51 cnt ++;52 }53 }54 ans = min(ans, make_pair(Abs(sum), cnt));///全部是后半部分的;55 56 it = M.lower_bound(-sum);///找到第一个大于-sum的位置,然后取两种情况的最小值;57 58 if(it != M.end())59 ans = min(ans, make_pair(Abs(sum+it->first), cnt+it->second));60 if(it != M.begin())61 {62 it--;63 ans = min(ans, make_pair(Abs(sum+it->first), cnt+it->second));64 }65 }66 printf("%I64d %d\n", ans.first, ans.second);67 }68 return 0;69 }

 

转载于:https://www.cnblogs.com/mj-liylho/p/9453395.html

你可能感兴趣的文章
POJ 3077 Rounders
查看>>
springMVC源码分析
查看>>
解决VS2010无法新建项目的问题
查看>>
彻底终结MySQL同步延迟问题
查看>>
cxGrid使用汇总3
查看>>
sqlserver 导入excel数据
查看>>
Android IOS WebRTC 音视频开发总结(五十)-- 技术服务如何定价?
查看>>
MyEclipse如何配置Struts2源码的框架压缩包
查看>>
数据系列:通过Windows Azure SQL数据库防火墙规则控制数据库访问
查看>>
Windows Azure 社区新闻综述(#72 版)
查看>>
git 删除文件
查看>>
GAN-生成对抗网络原理
查看>>
单片机
查看>>
liveshow回顾
查看>>
yii2中的场景使用
查看>>
AES加密,解密方法
查看>>
NOIP 2014 提高组 Day1
查看>>
bzoj千题计划254:bzoj2286: [Sdoi2011]消耗战
查看>>
搭建环境
查看>>
【原创】VMWare克隆或复制Linux虚拟机后无法上网的解决
查看>>