POJ3977:Subset——题解(三分+折半搜索)
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——题解(三分+折半搜索)的更多相关文章
- [题解](折半搜索)luogu_P4799_BZOJ_4800世界冰球锦标赛
抄的题解 以及参考:https://www.cnblogs.com/ZAGER/p/9827160.html 2^40爆搜过不了,考虑折半搜索,难点在于合并左右的答案,因为有可能答案同时载左右两边,我 ...
- [题解](折半搜索/高斯消元枚举自由元)BZOJ_1770_Lights
状压,时间空间都不行,如果每次搜索一半就可以省下很多空间,用map记下每种状态的答案,最后再把两次的答案合并 然而正解是高斯消元解异或方程组,最后搜索自由元 #include<iostream& ...
- 洛谷3067 BZOJ 2679题解(折半搜索)
传送门 BZOJ传送门(权限题) 看到n小于20,就可以想到搜索 所有的数要么在集合a中,要么在集合b中,要么都不在 可是3^n复杂度会炸,我们考虑优化 可以利用折半搜索,将前面一半的所有可能情况与后 ...
- 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 ...
- [NOIP10.4模拟赛]2.y题解--折半搜索+状压计数
题目链接: 咕 闲扯: 这题暴力分似乎挺多,但是一些奇奇怪怪的细节没注意RE了,还是太菜了 分析: 首先我们考虑最naiive的状压DP ,\(f[u][v][state]\)表示u开头,v结尾是否存 ...
- 折半搜索+Hash表+状态压缩 | [Usaco2012 Open]Balanced Cow Subsets | BZOJ 2679 | Luogu SP11469
题面:SP11469 SUBSET - Balanced Cow Subsets 题解: 对于任意一个数,它要么属于集合A,要么属于集合B,要么不选它.对应以上三种情况设置三个系数1.-1.0,于是将 ...
- 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
[LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...
- 【BZOJ4800】[CEOI2015 Day2]世界冰球锦标赛 (折半搜索)
[CEOI2015 Day2]世界冰球锦标赛 题目描述 译自 CEOI2015 Day2 T1「Ice Hockey World Championship」 今年的世界冰球锦标赛在捷克举行.\(Bob ...
- 【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)
[Usaco2012 Open]Balanced Cow Subsets 题目描述 给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\) ...
随机推荐
- 用列主元消去法分别解方程组Ax=b,用MATLAB程序实现(最有效版)
数值分析里面经常会涉及到用MATLAB程序实现用列主元消去法分别解方程组Ax=b 具体的方法和代码以如下方程(3x3矩阵)为例进行说明: 用列主元消去法分别解方程组Ax=b,用MATLAB程序实现: ...
- 如何借助windows的VHD引导特性实现VHD多windows系统共存
近期,由于一些需要,需要运行3个windows系统,具体需要如何此处略去,现将实现方式共享如下. 测试环境: HP 820 G2, 4G内存, 500G SSD硬盘 windows 7 企业版 win ...
- 浪在ACM新春大作战
题目链接: # Name 补题状态 A Memory and Crow 已补 B Memory and Trident 已补 C Memory and De-Evolution 已补 D Memory ...
- 259 [LeetCode] 3Sum Smaller 三数之和较小值
题目: Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 ...
- HDU 2485 Destroying the bus stations(!最大流∩!费用流∩搜索)
Description Gabiluso is one of the greatest spies in his country. Now he’s trying to complete an “im ...
- php 连接redis查询数据
class Layoutdemo{ function index(){ $db = new Db(); $id=390; $layout_json = array(); if($info = $db- ...
- C++课堂作业2016.05.04
GitHub/object-oriented 作业题目 开课后的第一次作业,简单地写了一个类,用成员函数来实现计算圆的面积. [代码] main.cpp #include "Area.h&q ...
- Median of Two Sorted Arrays(hard)
题目要求: 有两个排序的数组nums1和nums2分别为m和n大小. 找到两个排序数组的中位数.整体运行时间复杂度应为O(log(m + n)). 示例: 我的方法: 分别逐个读取两个数组的数,放到一 ...
- TCP系列37—Keep Alive—1、TCP存活检测
一.TCP存活(keepalive)检测的背景 对于TCP设计来说,如果一个客户端和服务器端建立连接后,不在进行数据传输,那么这个连接将会一直存在下去,理论上即使中间的路由器崩溃重启.或者中间的网络线 ...
- 无法打开mfc120.lib
今天在用VS2013编译OSG的时候报错:无法打开mfc120.lib.仔细查了下资料. 我是这么解决的: 安装Multibyte MFC Library for Visual Studio 2013 ...