http://poj.org/problem?id=3977

题目大意:有一堆数,取出一些数,记他们和的绝对值为w,取的个数为n,求在w最小的情况下,n最小,并输出w,n。

————————————————————

两天时间,终于搞下。

这题显然我们唯一能做到的只有暴力,但是2^35显然不可取……

但是显然我们折半搜索的话复杂度只有2^18左右所以没问题。

将数分成两堆,每一堆暴力求出所有情况并记录。

然后枚举第一堆,三分第二堆求解即可。

(为什么三分呢?因为绝对值啊,一定最优解是在函数的最低点,所以是单峰函数)

……思路挺简单是不是,但是注意以下几点:

1.n不为零,这点需要特判。

2.三分很容易写跪,具体怎么做看我代码。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll INF=;
inline ll abss(ll a){
if(a<)return -a;
return a;
}
struct num{
ll w;
ll n;
}mp1[],mp2[];
ll a[];
int cnt1=,cnt2=;;
bool in[];
void dfs(int n,int k,bool t){
memset(in,,sizeof(in));
if(!t){
mp1[++cnt1].w=mp1[cnt1].n=;
}
for(int res=;res<=((<<k)-);res++){
int cnt=;
int lz=res;
while(lz){
in[++cnt]=lz-lz/*;
lz/=;
}
ll sum=,num=;
for(int i=;i<=cnt;i++){
int j=i;
if(t)j+=n/;
if(in[i]){
sum+=a[j];
num++;
}
}
if(!t){
mp1[++cnt1].w=sum;
mp1[cnt1].n=num;
}else{
mp2[++cnt2].w=sum;
mp2[cnt2].n=num;
}
}
return;
}
bool cmp(num c,num d){
if(c.w<d.w)return ;
if(c.w>d.w)return ;
if(c.n<d.n)return ;
return ;
}
ll ans,cnt;
void sanfen(int l,int r,num k){
if(r-l<=){
ll t1=abss(k.w+mp2[l].w);
ll t2=abss(k.w+mp2[r].w);
ll t3=abss(k.w+mp2[(l+r)/].w);
ll c1=mp2[l].n+k.n;
ll c2=mp2[r].n+k.n;
ll c3=mp2[(l+r)/].n+k.n;
ll t,c;
if(t1>t2||(t1==t2&&c1>c2)){
t=t2;c=c2;
}else{
t=t1;c=c1;
}
if(t>t3||(t==t3&&c>c3)){
t=t3;c=c3;
}
if(ans>t||(ans==t&&cnt>c)){
ans=t;cnt=c;
}
return;
}
int mid1=(r+*l)/;
int mid2=(l+*r)/;
ll t1=abss(k.w+mp2[mid1].w);
ll t2=abss(k.w+mp2[mid2].w);
if(t1<t2||(t1==t2&&mp2[mid1].n+k.n<mp2[mid2].n+k.n)){
sanfen(l,mid2-,k);
}else{
sanfen(mid1+,r,k);
}
return;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF&&n){
cnt1=,cnt2=;
for(int i=;i<=n;i++){
scanf("%lld",&a[i]);
}
dfs(n,n/,);
dfs(n,n-n/,);
sort(mp2+,mp2+cnt2+,cmp);
//for(int i=1;i<=cnt1;i++)printf("1 %lld %lld\n",mp1[i].w,mp1[i].n);
//for(int i=1;i<=cnt2;i++)printf("2 %lld %lld\n",mp2[i].w,mp2[i].n);
ans=INF;cnt=INF;
for(int i=;i<=cnt1;i++){
sanfen(,cnt2,mp1[i]);
if(i>){
if(ans>abss(mp1[i].w)||(ans==abss(mp1[i].w)&&cnt>mp1[i].n)){
ans=abss(mp1[i].w);cnt=mp1[i].n;
}
}
}
printf("%lld %lld\n",ans,cnt);
}
return ;
}

POJ3977:Subset——题解(三分+折半搜索)的更多相关文章

  1. [题解](折半搜索)luogu_P4799_BZOJ_4800世界冰球锦标赛

    抄的题解 以及参考:https://www.cnblogs.com/ZAGER/p/9827160.html 2^40爆搜过不了,考虑折半搜索,难点在于合并左右的答案,因为有可能答案同时载左右两边,我 ...

  2. [题解](折半搜索/高斯消元枚举自由元)BZOJ_1770_Lights

    状压,时间空间都不行,如果每次搜索一半就可以省下很多空间,用map记下每种状态的答案,最后再把两次的答案合并 然而正解是高斯消元解异或方程组,最后搜索自由元 #include<iostream& ...

  3. 洛谷3067 BZOJ 2679题解(折半搜索)

    传送门 BZOJ传送门(权限题) 看到n小于20,就可以想到搜索 所有的数要么在集合a中,要么在集合b中,要么都不在 可是3^n复杂度会炸,我们考虑优化 可以利用折半搜索,将前面一半的所有可能情况与后 ...

  4. Codeforces Round #297 (Div. 2)E. Anya and Cubes 折半搜索

    Codeforces Round #297 (Div. 2)E. Anya and Cubes Time Limit: 2 Sec  Memory Limit: 512 MBSubmit: xxx  ...

  5. [NOIP10.4模拟赛]2.y题解--折半搜索+状压计数

    题目链接: 咕 闲扯: 这题暴力分似乎挺多,但是一些奇奇怪怪的细节没注意RE了,还是太菜了 分析: 首先我们考虑最naiive的状压DP ,\(f[u][v][state]\)表示u开头,v结尾是否存 ...

  6. 折半搜索+Hash表+状态压缩 | [Usaco2012 Open]Balanced Cow Subsets | BZOJ 2679 | Luogu SP11469

    题面:SP11469 SUBSET - Balanced Cow Subsets 题解: 对于任意一个数,它要么属于集合A,要么属于集合B,要么不选它.对应以上三种情况设置三个系数1.-1.0,于是将 ...

  7. 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)

    [LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...

  8. 【BZOJ4800】[CEOI2015 Day2]世界冰球锦标赛 (折半搜索)

    [CEOI2015 Day2]世界冰球锦标赛 题目描述 译自 CEOI2015 Day2 T1「Ice Hockey World Championship」 今年的世界冰球锦标赛在捷克举行.\(Bob ...

  9. 【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)

    [Usaco2012 Open]Balanced Cow Subsets 题目描述 给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\) ...

随机推荐

  1. Ruby学习系列一,基本认识

    安装Ruby后,打开命令行,先来看下Ruby的版本. ruby -v ,如果看到类似 ruby 1.9.3p392.... ,说明我们的Ruby安装成功了. 然后我们输入 irb ,进入Ruby的交互 ...

  2. PHP数组中插入元素

    1. array_unshift()数组头插入新元素 $fruits = array('apple','pear','banana','orange'); array_unshift($fruits, ...

  3. 必读的 Android 文章

    必读的 Android 文章 掘金官方 关注 2017.06.07 13:58* 字数 25218 阅读 8782评论 2喜欢 218 写给 Android 开发者的混淆使用手册 - Android ...

  4. 从零学习安全测试,从XSS漏洞攻击和防御开始

    WeTest 导读 本篇包含了XSS漏洞攻击及防御详细介绍,包括漏洞基础.XSS基础.编码基础.XSS Payload.XSS攻击防御. 第一部分:漏洞攻防基础知识   XSS属于漏洞攻防,我们要研究 ...

  5. 「日常训练」Divisibility by Eight(Codeforces Round 306 Div.2 C)

    题意与分析 极简单的数论+思维题. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #de ...

  6. linux系统简单命令

    # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # hostn ...

  7. GIT: 分布式开发 代码管理工具使用命令大全

    代码管理工具: GIT     什么是GIT? Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目 Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常 ...

  8. JAVA 面试须知

    本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺. 1. Java中的原始数据类型都有哪些, ...

  9. Visual Stdio Code编辑Mark Down

    Visual Studio Code可以一边写Markdown一边预览了,而且不需要任何插件. 方法如下: 新建一个文件,以 .md 为后缀: Visual Studio Code 原生就支持高亮Ma ...

  10. logisitic回归

    线性回归目的是找到一条直线(或者超平面)尽可能地接近所有的训练数据点,而对数几率回归的目的是找到一条直线(或者超平面)尽可能地分开两种不同类别的数据点. 对数几率回归感觉更像是一个分类问题.https ...