二分查找,简而言之就是在一个有序的序列中找一个元素,因为这些元素已经有序,所以每次都将要找的数跟待寻找序列的中间元素比较,如果要找的数大于中间元素,说明接下来只需要在该序列的右半边中找,所以可以不用管左半边了,这样每次都排除一半的元素直到最后找到要找的元素。我们可以用两个变量代表待寻找序列的最左端索引(l)和最右端索引(r),然后两个变量的中间元素是mid,再经过比较之后考虑将r移动到mid处成为下一次寻找的新的r值,还是将l值移动到mid+1处成为下一次寻找的l值。



代码模板:

while(l < r){
int mid = l + (r-l) / 2; //不直接用(l+r)/2是为了防止l+r的时候溢出
if(judge(mid)) l = mid+1; //judge函数是自己定义的,判断要找的数在序列的哪半边的
else r = mid;
}

因为这样找的情况之下

需要注意一个细节的关于边界的问题:假设要在100个排好序的数中找到某数(这个数的索引最后我们得知是8),最后这个while循环只会等到 l 和 r 两个数相等的时候才会停止,当循环停止的时候 ,并不知道上一个循环的lr分别是7和8,然后是l被赋值成为mid+1得到8的,还是l与r原本为8和9,然后r被赋值成为mid的,所以这个时候需要在最后再判断一下,因为循环结束的时候l和r已经相等了,所以他们指向的位置如果不是要找的数,那么l-1(或者说r-1)处的元素才是我们要找的元素



下面给出二分法的例题

POJ 1046

https://vjudge.net/problem/POJ-1064

最最简单的二分查找

题意大概是有N根木棍,然后每一根都有着自己的长度,现在要求截断这些木棍,给出K根长度相等的木棍,问最长能截成多长(不能拼接)。

那就直接用二分法做,从0到最长木棍的长度这样一直往最合适的点逼近即可,然后每次有了猜测的长度mid之后,就遍历所有木棍,然后将每一根木棍都截出尽可能多小木棍,也就是直接 / mid ,然后加到总数中啦。

但是要注意一个特殊的地方,就是除零的时候可能出错(在下方代码中也标出来了)

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100500;
int N,K,k,ma = 0;
double b,ans;
int c[maxn]; bool judge(int mid, int k){
int sum = 0;
if(mid == 0) return 0; //这里如果不直接返回0的话可能在下下行 /mid的时候发生除零错
for(int i=0;i<N;i++){
sum += c[i] / mid;
if(sum >= k) return 1;
}
return 0;
} void binsearch(int l,int r,int k){
while(l<r){
int mid = (r-l)/2+l;
if(judge(mid,k)) l = mid+1;
else r = mid;
}
if(judge(l,k)) ans = double(l) / 100.0;
else ans = double(l-1) / 100.0;
} int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
#endif
scanf("%d%d",&N,&K);
for(int i=0;i<N;i++){
scanf("%lf",&b);
c[i] = int(b * 100);
if(c[i] > ma) ma = c[i];
}
sort(c,c+N,greater<int>());
binsearch(0,c[0],K);
if(ans < 0.01) ans = 0.00;
printf("%.2f\n",ans);
return 0;
}

稍难一点的题是 POJ-2456

https://vjudge.net/problem/POJ-2456

题意比较简单,就是有N个点在数轴上排成一横排,你要从中取C个点使得这C个点中任意两个点之间的最短距离最大。首先看到任意两个点之间的最短距离,那这个距离肯定从相邻i啷个点之间的距离中来选出,因为如果a,b,c三个点依次从左到右排开,也就是说ab两个点相邻而ac两个点不相邻,那么ac之间的距离肯定大于ab。

然后这个题就是我们说到的最大化最小值的问题,因为它要满足两个要求(又要是所有间距中最小,又要是所有分配方案中最大)而贪心基本上除了一些特殊的处理(比如poj2010等等)只能满足往一个条件去贪,这样就比较难做。

但是二分就可以解决这个问题,毕竟是要找一个数嘛,那么我们其实还是一个一个地去尝试,只不过二分了之后可以每次试玩排除一半的数,这样就降低了复杂度。

基本思路就是先取l为最小距离(一般就是0啦),然后再取任意两点之间距离的最大值(也就是第一个点和最后一个点之间的距离),然后我们的所有的值就在这中间找啦。每次判断中间值是否符合要求,因为我们要找的是尽量大,所以一旦符合要求,我们就删掉左半边序列,往右半边去找,反之才往左半边去找,那么怎么才能够判断是否符合要求呢?

既然这个时候中间值mid是我们猜测的一个解,那么首先它需要满足它是所有间隔中的最小值,我们就所以任意间隔都要比他大,我们从最左边的点开始,依次遍历所有点,然后每当凑到距离>= mid了之后,就表示我们可以选这个遍历了的点,然后继续往下走,如果凑到了C个点,就说明这个mid是符合要求的,(反之如果所有点都遍历完了,还没有凑到C个点,就说明该mid不符合要求,不是我们要的解),如果符合要求了,那么再到它的右边去找,(上述操作就是代码中的judge过程,也就是判断中间这个数能否满足我们的基础要求(即所有间距中的最小值),二分的过程就是找这些值中的最大)

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int maxn = 100150;
int N,C;
int a[maxn];
bool judge(int x){
int cur = a[0],num = 1;
for(int i=1;i<N;i++){
if(a[i] - cur >= x) {
num++;
cur = a[i];
}
if(num >= C) return true;
}
return false;
} void solve(){
int l = 0,r = a[N-1] - a[0];
while(l < r){
int mid = l + (r-l) / 2; //不直接用(l+r)/2是为了防止l+r的时候溢出
if(judge(mid)) l = mid+1;
else r = mid;
}
if(judge(r)) cout<<r<<endl;
else cout<<l-1<<endl;
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%d%d",&N,&C);
for(int i=0;i<N;i++){
scanf("%d",&a[i]);
}
sort(a,a+N);
solve();
return 0;
}

二分法(POJ-1064与POJ-2456)的更多相关文章

  1. POJ 1064 Cable master(二分查找+精度)(神坑题)

    POJ 1064 Cable master 一开始把 int C(double x) 里面写成了  int C(int x) ,莫名奇妙竟然过了样例,交了以后直接就wa. 后来发现又把二分查找的判断条 ...

  2. poj 1064 Cable master 判断一个解是否可行 浮点数二分

    poj 1064 Cable master 判断一个解是否可行 浮点数二分 题目链接: http://poj.org/problem?id=1064 思路: 二分答案,floor函数防止四舍五入 代码 ...

  3. POJ 1064 1759 3484 3061 (二分搜索)

    POJ 1064 题意 有N条绳子,它们长度分别为Li.如果从它们中切割出K条长度相同的绳子的话,这K条绳子每条最长能有多长?答案保留小数点后2位. 思路 二分搜索.这里要注意精度问题,代码中有详细说 ...

  4. 二分搜索 POJ 1064 Cable master

    题目传送门 /* 题意:n条绳子问切割k条长度相等的最长长度 二分搜索:搜索长度,判断能否有k条长度相等的绳子 */ #include <cstdio> #include <algo ...

  5. POJ 1201 Intervals || POJ 1716 Integer Intervals 差分约束

    POJ 1201 http://poj.org/problem?id=1201 题目大意: 有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai, ...

  6. POJ 1064 Cable master (二分法+精度控制)

    Cable master Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65358   Accepted: 13453 De ...

  7. 第三章 poj 1064——关于带精度的二分法

    /* 题意:给定n个实数l[i],给定一个k 问:求最大的ans,使得sum l[i]/ans i=1 to n >=k,且ans最大*/ #include <iostream> # ...

  8. POJ 1064 (二分)

    题目链接: http://poj.org/problem?id=1064 题目大意:一堆棍子可以截取,问要求最后给出K根等长棍子,求每根棍子的最大长度.保留2位小数.如果小于0.01,则输出0.00 ...

  9. poj 1064 (二分+控制精度) && hdu 1551

    链接:http://poj.org/problem?id=1064 Cable master Time Limit: 1000MS   Memory Limit: 10000K Total Submi ...

  10. POJ 1064 Cable master (二分答案)

    题目链接:http://poj.org/problem?id=1064 有n条绳子,长度分别是Li.问你要是从中切出m条长度相同的绳子,问你这m条绳子每条最长是多少. 二分答案,尤其注意精度问题.我觉 ...

随机推荐

  1. JDK12的新特性:CompactNumberFormat

    目录 简介 CompactNumberFormat详解 自定义CompactNumberFormat 解析CompactNumber 总结 JDK12的新特性:CompactNumberFormat ...

  2. OpenHarmony有氧拳击之设备端开发

    一.简介 在一个风和日丽,阳光明媚的下午,码农们都像往常一样正在专注地码代码.突然前面的小哥哥站起来,手握开发板,来回出拳.这是怎么回事? 原来这是一款拳击互动游戏,本文将带你一同解开其中的奥秘.开发 ...

  3. JS 取Json中对象特定属性值

    解析JSON JSON 数据 var str = '[{"a": "1","b": "2"}, {"a&quo ...

  4. WAF 原理入门

    WAF 入门 WAF 功能 WAF 全称叫 Web Application Firewall,和传统防火墙的区别是,它是工作在应用层的防火墙,主要对 web 请求/响应进行防护.那么 WAF 有什么功 ...

  5. 从ID3到LGB

    梳理一下树模型算法,从三种最基础的tree到lgb的全过程笔记 基于信息增益(Information Gain)的ID3算法 ID3算法的核心是在数据集上应用信息增益准则来进行特征选择,以此递归的构建 ...

  6. spring-jdbc5新特性,一个配置文件解决临时修改数据库的问题

    import java.sql.SQLException; import java.util.List; import java.util.Map; import javax.sql.DataSour ...

  7. vue3 快速入门系列 —— 组件通信

    vue3 快速入门系列 - 组件通信 组件通信在开发中非常重要,通信就是你给我一点东西,我给你一点东西. 本篇将分析 vue3 中组件间的通信方式. Tip:下文提到的绝大多数通信方式在 vue2 中 ...

  8. vue项目node-scss装不上问题( vue执行npm install报错: Can‘t find Python executable “python“, you can set the PYTHON env variable

    一.描述从网上下载的一个Vue模板项目,导入VsCode,执行npm install命令后,报错了,报错的信息是node-sass安装失败,同时提示需要python环境的错误信息,这是因为安装node ...

  9. Stable Diffusion中的常用术语解析

    Stable Diffusion中的常用术语解析 对于很多初学者来说,会对Stable Diffusion中的很多术语感到困惑,当然你不是唯一的那个. 在这篇文章中,我将会讲解几乎所有你在Stable ...

  10. MySQL正则表达式:REGEXP 和 LIKE

    正则表达式作用: 根据指定的匹配模式匹配文中符合要求的特殊字符. REGEXP : ①操作符中常用的匹配列表: ②匹配特殊字符使用\\进行转义 \\.   能够匹配 . \\f   换页 \\n 换行 ...