折半枚举——poj3977
暴力搜索超时,但是折半后两部分状态支持合并的情况,可用折半枚举算法
poj3977 给一个序列a[],从里面找到k个数,使其和的绝对值最小
经典折半枚举法+二分解决,对于前一半数开一个map,map[sum]里存下凑出当前sum的最小元素个数
枚举后面一半的所有情况,然后lower_bound去找map里最接近-sum的元素,由于要求输出sum最小并且num也尽量小的答案,所以用pair来存答案
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
#define N 45
#define PI 4*atan(1.0)
#define mod 1000000007
#define met(a, b) memset(a, b, sizeof(a))
#define INF 10000000000000000
typedef long long LL; int n;
LL a[N]; LL Abs(LL x){return x<?-x:x;}
int main(){
while(scanf("%d", &n), n){
for(int i=; i<n; i++)
scanf("%I64d", &a[i]); map<LL, int> M;
map<LL, int>::iterator it;
pair<LL, int> ans(Abs(a[]), ); for(int i=; i<<<(n/); i++){
LL sum = ;int cnt = ;
for(int j=; j<(n/); j++){
if((i>>j)&){
sum += a[j];
cnt ++;
}
}
ans = min(ans, make_pair(Abs(sum), cnt));///全部是前半部分的;
if(M[sum])///更新cnt为小的;
M[sum] = min(M[sum], cnt);
else
M[sum] = cnt;
} for(int i=; i<<<(n-n/); i++){
LL sum = ;int cnt = ;
for(int j=; j<(n-n/); j++){
if((i>>j)&){
sum += a[j+n/];
cnt ++;
}
}
ans = min(ans, make_pair(Abs(sum), cnt));///全部是后半部分的; it = M.lower_bound(-sum);///找到第一个大于-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("%I64d %d\n", ans.first, ans.second);
}
return ;
}
折半枚举——poj3977的更多相关文章
- Load Balancing 折半枚举大法好啊
Load Balancing 给出每个学生的学分. 将学生按学分分成四组,使得sigma (sumi-n/4)最小. 算法: 折半枚举 #include <iostrea ...
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- NYOJ 1091 超大01背包(折半枚举)
这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序 ...
- Codeforces 888E - Maximum Subsequence(折半枚举(meet-in-the-middle))
888E - Maximum Subsequence 思路:折半枚举. 代码: #include<bits/stdc++.h> using namespace std; #define l ...
- Codeforces 912 E.Prime Gift (折半枚举、二分)
题目链接:Prime Gift 题意: 给出了n(1<=n<=16)个互不相同的质数pi(2<=pi<=100),现在要求第k大个约数全在所给质数集的数.(保证这个数不超过1e ...
- poj_3977 折半枚举
题目大意 给定N(N<=35)个数字,每个数字都<= 2^15. 其中一个或多个数字加和可以得到s,求出s的绝对值的最小值,并给出当s取绝对值最小值时,需要加和的数字的个数. 题目分析 需 ...
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- poj 3977 Subset(折半枚举+二进制枚举+二分)
Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 5721 Accepted: 1083 Descripti ...
- CodeForces888E Maximum Subsequence(折半枚举+two-pointers)
题意 给定一个包含\(n\)个数的序列\(a\),在其中任选若干个数,使得他们的和对\(m\)取模后最大.(\(n\leq 35\)) 题解 显然,\(2^n\)的暴枚是不现实的...,于是我们想到了 ...
随机推荐
- 过滤字符串中的html标签
C#中,我们有时需要过滤掉字符串中的部分html标签,以下是一些简单的html标签过滤方法,使用的主要方式是正则表达式 public static string ClearHtml(string ht ...
- 开源实践分享:Ceph bluestore部署实践
https://blog.51cto.com/99cloud/2119884 Ceph bluestore部署 首先为大家分享Ceph bluestore具体该如何部署,使用环境如下• 单节点• Ce ...
- php strrev()函数 语法
php strrev()函数 语法 strrev()怎么用? php strrev()函数用于反转字符串,语法是strrev(string),返回已反转的字符串.大理石构件来图加工 作用:反转字符串 ...
- Qt事件学习
一.创建Qt gui应用对应的源码: 点击(此处)折叠或打开 //mylineedit.h #ifndef MYLINEEDIT_H #define MYLINEEDIT_H #include < ...
- spring boot2.x集成spring security5与druid1.1.13(一)
版本: spring boot 2.1.2.RELEASE druid-spring-boot-starter 1.1.13 步骤: 一.maven ...
- Python每日一题 004
将 0001 题生成的 200 个激活码(或者优惠券)保存到 Redis 非关系型数据库中. 代码 import redis import uuid # 创建实例 r=redis.Redis(&quo ...
- Sqli labs系列-less-5&6 报错注入法(下)
我先输入 ' 让其出错. 然后知道语句是单引号闭合. 然后直接 and 1=1 测试. 返回正常,再 and 1=2 . 返回错误,开始猜表段数. 恩,3位.让其报错,然后注入... 擦,不错出,再加 ...
- Nginx在Windows平台的配置
Nginx在Windows平台的配置 能够使用Nginx搭建Tomcat集群,并完成负载均衡. 1.什么是Nginx 2.为什么使用Nginx 背景: 互联网飞速发展的今天,大用户量高并发已经成为互联 ...
- C++ placement new与内存池
参考:https://blog.csdn.net/Kiritow/article/details/51314612 有些时候我们需要能够长时间运行的程序(例如监听程序,服务器程序)对于这些7*24运行 ...
- PAT 1051 Pop Sequence (25 分)
返回 1051 Pop Sequence (25 分) Given a stack which can keep M numbers at most. Push N numbers in the ...