poj3977 - subset - the second time - 暴力 + 二分
2017-08-26 11:38:42
writer:pprp
已经是第二次写这个题了,但是还是出了很多毛病
先给出AC代码:
解题思路:
之前在培训的时候只是笼统的讲了讲怎么做,进行二分对其中一边进行暴力枚举,对另一边用lower_bound查找算出的相反数
现在给出详细一点的思路:
答案可能在左边枚举的部分,也可能在右边枚举的部分,也可能在两边加起来的和中
所以从这三个方面不能少考虑;
还有用到了map所以算出来的key是唯一的,所以当算出来两个key相等的时候,应该采用value也就是cnt比较小的那个数
细节比较多,很容易就wa
/*
@prama: poj 3977
@writer:pprp
@declare:暴力+二分
@date:2017/8/26
*/ #include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#define ll long long
#define IOS ios::sync_with_stdio(false),cin.tie(0);
#define tag cout <<"-------" << endl; using namespace std;
int N;
const int maxn = ;
ll subset[maxn]; //改成ll ll ll_abs(ll a)
{
return a > ? a:- a;
} int main()
{
IOS;
while(cin >> N && N)
{
memset(subset,,sizeof(subset));
for(int i = ; i < N ; i++)
cin >> subset[i]; //初始化这个pair,用来记录答案
pair<ll,int> ans(ll_abs(subset[]),);
map<ll,int> mp;// sum -> cnt //二进制枚举前一半
for(int i = ; i < ( << N/) ; i++)
{
ll sum = ;
int cnt = ;
for(int j = ; j < N/ ; j++)
{
//二进制枚举,判断第j为是否被选中
if((i >> j)&)
{
sum += subset[j];
cnt++;
}
}
//**增加一个判断,如果一个都没有被选中
if(cnt == ) continue; //对结果进行操作,找到当前最小的sum
ans = min(ans, make_pair(ll_abs(sum),cnt)); //将每次枚举的情况都加入map中去
map<ll,int>::iterator ii = mp.find(sum);
if(ii != mp.end())//如果能找到,就采用那个比较小的cnt,因为map的key是unique的所以要进行如下判断
ii->second = min(ii->second,cnt);
else //如果没有找到就直接放到map中去
mp[sum] = cnt;
} //对后一半进行枚举,得到的sum可从map中寻找最接近-sum的值
for(int i = ; i < ( << (N - N/)); i++)
{
ll sum = ;
int cnt = ;
for(int j = ; j < (N - N/); j++)
{
if((i >> j) & )
{
cnt++;
sum += subset[N/ +j];
}
}
//**增加一个判断,如果一个都没有被选中
if(cnt == ) continue;
//对结果进行操作,找到当前最小的sum
ans = min(ans, make_pair(ll_abs(sum),cnt)); //对后半段进行找最接近于-sum的值
//运用lower_bound查找的是不小于-sum的值,就是比-sum略大的值
map<ll,int>::iterator it = mp.lower_bound(-sum);
if(it != mp.end())//如果可以找到就进行比较
{
ans = min(ans, make_pair(ll_abs(it->first + sum),it->second+cnt));
} // 有可能是比-sum略小的值,这个也可以用upper_bound来写 ??
if(it != mp.begin())
{
it--;
ans = min(ans, make_pair(ll_abs(it->first + sum),it->second+cnt));
}
//经过测试,不可以采用这个方法
map<ll,int>::iterator tt = mp.upper_bound(-sum);
{
ans = min(ans, make_pair(ll_abs(it->first + sum),it->second+cnt));
}
} cout << ans.first << " " << ans.second << endl;
}
return ;
}
遇到的问题:
1、数据类型的选择,数据范围是10^15 远远超过int类型了,所以一开始没有检查数组类型,导致wa了很多次,
也浪费了很长时间。
2、lower_bound和upper_bound的用法还是不是很清楚。
最后那部分不可以用upper_bound直接将指针进行移动就可以
poj3977 - subset - the second time - 暴力 + 二分的更多相关文章
- 8VC Venture Cup 2016 - Elimination Round E. Simple Skewness 暴力+二分
E. Simple Skewness 题目连接: http://www.codeforces.com/contest/626/problem/E Description Define the simp ...
- Subset POJ - 3977(折半枚举+二分查找)
题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ...
- Codeforces Round #367 (Div. 2) A B C 暴力 二分 dp(字符串的反转)
A. Beru-taxi time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- Subsequence(暴力+二分)
Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10875 Accepted: 4493 Desc ...
- Vijos P1116 一元三次方程求解【多解,暴力,二分】
一元三次方程求解 描述 有形如:ax^3+bx^2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之 ...
- I Count Two Three HDU - 5878(暴力二分)
为甚么16年Qingdao Online 都是暴力题emm///... 先暴力预处理 然后lower _bound二分 #include <iostream> #include <c ...
- HDU6127 简单几何 暴力二分
LINK 题意:给出n个点,每个点有个权值,可以和任意另外一点构成线段,值为权值积.现问过原点的直线中交所有线段的权值和的最大值,注意直线必不经过点. 思路:直线可以将点集分为两侧,此时的权值为两侧点 ...
- Codeforces Beta Round #3 B. Lorry 暴力 二分
B. Lorry 题目连接: http://www.codeforces.com/contest/3/problem/B Description A group of tourists is goin ...
- Codeforces Round #345 (Div. 2) D. Image Preview 暴力 二分
D. Image Preview 题目连接: http://www.codeforces.com/contest/651/problem/D Description Vasya's telephone ...
随机推荐
- 解决kindeidtor与struts2框架交互WARN OgnlValueStack:68 - Error setting value [[Ljava.lang.String;@10da4df]的bug
当用使用ssh框架,前端用到kindeitor富文本编辑器时候,上传文件后有一个图片管理.当点击图片管理的时候,在后台会报一个异常: WARN OgnlValueStack:68 - Error se ...
- CentOS下调整home和根分区大小的方法
解决外挂硬盘的问题. 目标:将VolGroup-lv_home缩小到20G,并将剩余的空间添加给VolGroup-lv_root 1.首先查看磁盘使用情况[root@jb51.net~]# df -h ...
- ssh无密码登录设置
为啥要设置ssh无密码登录? 我们先来看一下分布式系统的一键启动流程, 在matser机器上运行脚本,脚本检测有多少slavers,然后通过ssh登录到slavers,进入到相同的目录(或者通过$XX ...
- volatile变量,java内存模型
volatile变量提供了最轻量级的同步机制,当一个变量加上volatile修饰时,会具有一下两个特性 https://blog.csdn.net/u011277123/article/details ...
- lnmp1.4环境下thinkphp3.2配置pathinfo模式
1.打开php.ini 通常该文件在 /usr/local/php/etc/php.ini vi /usr/local/php/etc/php.ini 找到 cgi.fix_pathinfo,默认为0 ...
- lamp环境的搭建和安装
最近,部门有些系统需要迁移到新的机器上,因此需要在新的机器上安装lamp和lnmp的环境,因此在这里总结一下: 一. 安装lamp环境的步骤: (1).因为是新的机器,因此需要安装gcc的各种环境: ...
- 有按钮的ListView
有按钮的ListView 但是有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮.添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上 ...
- 如何检测浏览器是否安装了Adblock,uBlock Origin,Adguard,uBlock等广告屏蔽插件
由于我们网站上的广告经常被一些广告插件给屏蔽掉,上级给我下达了一个检测浏览器是否安装了屏蔽广告的插件的任务. 经过研究,借鉴,参考,整合了如下三种解决方案. 方案一: 利用广告插件通过对含有goo ...
- Linux系统——awk命令
awk命令不仅仅是Linux系统的命令,也是一种编程语言,用来处理数据和生成报告(Exel),处理的数据可以是一个或多个文件(标准输入和管道获取标准输入).可在命令行上编辑操作,也可以写成awk程序运 ...
- 2-AMD
诞生背景1.随着前端逻辑越来越多,项目越来越大,开发大型项目就必须分模块开发2.一切都那么完美,在NodeJs实现后,当人们开始热情的打算把这种实现也用于浏览器时,却发现并不适合.NodeJS应用加载 ...