从两道基础二分算法题谈check函数的写法
第一题:愤怒的牛 loj链接
5 3
1 2 8 4 9
根据上面的样例,首先对牛舍进行排序,可以得到
1 2 4 8 9
可以有以下几种方案(将牛安排在以下编号的牛舍)
1
2
4
此方案牛与牛最小的距离为1
1
4
8
此方案牛与牛最小的距离为3
1
4
9
此方案牛与牛最小的距离为3
2
4
8
此方案牛与牛最小的距离为2
2
4
9
此方案牛与牛最小的距离为2
……
从以上方案可以看出,就是要尽可能的让最小距离最大。再来看看下面的代码
bool chk(int t){int sum=a[1],ans=1;for(int i=2;i<=n;i++){if(sum+t>a[i]) continue;else{sum=a[i];ans++;}}return ans>=m;
}
通过样例的数据,对照上面的代码不难得到,
当t=1
的时候,ans=5;
当t=2
或者t=3
都可以满足ans=3;
当t>=4
的时候,ans=2;
因此,只有当t=2或者t=3
才能满足条件(样例共3头牛),显然,t=3才符合题意,那么,怎么确保t尽量取到更大的值呢?
可以这样分析,当ans>m的情况那么一定是二分值太小,而ans<m则是二分值太大,
于是为了让t
取到更大的值应该采用if(chk(t)) l=mid
,这样求出的二分值更大。
while(l<r-1){int mid=(l+r)/2;if(chk(mid)) r=mid;else l=mid;}
如果把chk函数里面的返回值改成
return ans<=m
,配上if(chk(t)) r=mid;else l=mid
这样,表面上看没什么错误,实际上最终求出的二分值是更小的,这是不符合题意的。
第二题:数列分段 loj链接
5 3
4 2 4 5 1
对照样例数据,可以采用如下集中切法:
4 2
|4 5
|1
三段之和分别为6
9
1
,和的最大值为9
4
|2 4
|5 1
三段之和分别为4
6
6
,和的最大值为6
以上两种切割的方法都是分成3段,但是,依据题意,更优的切割方法是第二种.
接下来看看本题正确的check函数的写法
bool chk(int x){int sum=0,tot=1;for(int i=1;i<=n;i++){if(sum+a[i]<=x) sum+=a[i];else{tot++;sum=a[i];}}return tot<=m;
}
和第一题一样,考虑到存在tot=m
的情况下,其二分值不是最优的(样例中的第1种切割方法),应该尽量让二分值尽可能的小又同时满足tot=m
这个前提。
如果tot<=m
,说明是二分值偏大,因此可以采用 if(chk(x)) r=mid;else l=mid
,这样就可以满足tot=m
的同时,二分值最小。
while(l<r-1){int mid=(l+r)/2;if(chk(mid))r=mid;else l=mid;}
需要注意的是,本题的二分算法的初值必须让 l=max(ai)l=max(ai)l=max(ai),r=sum(ai)r=sum(ai)r=sum(ai)。
如果把chk函数里面的返回值改成
return ans>=m
,配上if(chk(t)) l=mid;else r=mid
这样,表面上看没什么错误,实际上最终求出的二分值虽然满足了分成了m段,但是二分值却是更大的,(第一种切割方法就属于这种情况)这是不符合题意的。
第一题完整代码
#include <bits/stdc++.h>
using namespace std;
int n,m,a[100008];
bool chk(int t){int g=a[1],ans=1;for(int i=2;i<=n;i++){if(g+t>a[i]) continue;else{g=a[i];ans++;}}return ans>=m;
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",a+i);sort(a+1,a+n+1);int l=a[1],r=a[n];while(l<r-1){int midl=(l+r)>>1;if(chk(midl)) l=midl;else r=midl;}if(chk(l)) printf("%d",l);else printf("%d",r);return 0;}
第二题完整代码
#include <bits/stdc++.h>
using namespace std;
int n,m,a[100005],maxx=-1,cnt;
bool chk(int x){int sum=0,tot=1;for(int i=1;i<=n;i++){if(sum+a[i]<=x) sum+=a[i];else{tot++;sum=a[i];}}return tot<=m;
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",a+i);maxx=max(maxx,a[i]);cnt+=a[i];}int l=maxx,r=cnt;while(l<r-1){int mid=(l+r)/2;if(chk(mid))r=mid;else l=mid;}if(chk(l)) printf("%d",l);else printf("%d",r);return 0;}
从两道基础二分算法题谈check函数的写法相关推荐
- 我整理了50道经典Java算法题,直接进了字节跳动!!
写在前面 最近,很多小伙伴都想进入字节跳动这个快速发展的公司,而字节跳动对于算法的要求比较高.于是乎,有些小伙伴问我能否整理一些基础的算法题,帮助他们提升下基础算法能力.我:没问题啊!于是,经过半个多 ...
- 130道基础OJ编程题之: 47 ~ 57 道
130道基础OJ编程题之: 47 ~ 57 道 文章目录 130道基础OJ编程题之: 47 ~ 57 道 0. 昔日OJ编程题: 47. BC50 计算单位阶跃函数 48. BC51 三角形判断 49 ...
- java经典100例算法题_10道java经典算法题,每一题都能帮你提升java水平!
JAVA经典算法题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析:兔子 ...
- 语言高精度算法阶乘_JavaScript中的算法(附10道面试常见算法题解决方法和思路)...
https://juejin.im/post/6844903811505455118 Introduction 面试过程通常从最初的电话面试开始,然后是现场面试,检查编程技能和文化契合度.几乎毫无例外 ...
- 80道漫画图解算法题汇总(0406版本)
各位好,本人自2019年1月以来,连续写了80余篇算法题解(主要针对高频面试题),都采用漫画图解的方式,为了大家查阅方便,我对目录进行了汇总,大家有兴趣的可以收藏一下,以备不时之需.(另外,为了感谢大 ...
- java求最大公约数_10道java经典算法题,小白必备,每一题都能提升你的java能力...
JAVA经典算法 跪求关注,祝关注我的人都:身体健康,财源广进,福如东海,寿比南山,早上贵子,从不掉发! 更多java资料可以私信我领取! [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每 ...
- 两道有趣的逻辑推理题
海盗分金币 问题: 有5个海盗,按照等级从5到1排列.最大的海盗有权提议他们如何分享100枚金币.但其他人要对此表决,如果多数(所有人中的多数)反对,那他就会被杀死.他应该提出怎样的方案,既让自己拿到 ...
- 漫画图解python_80道漫画图解算法题汇总
本文每个链接采用漫画图解的方式,为了大家查阅方便,对目录进行了汇总,大家有兴趣的可以收藏一下,以备不时之需. 01 PART 二分法系列 介绍:二分法自不必说,是面试以及比赛的高频考点,必须掌握. 0 ...
- 两道动态规划买股票的题
T1:给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格. 在每一天,你可能会决定购买和/或出售股票.你在任何时候 最多 只能持有 一股 股票.你也可以购买它,然后在 同 ...
最新文章
- Latex之WinEdt编辑界面的自动换行
- wcf寄宿iis7是的 500错误
- python 发邮件 timeout_python发送邮件
- IDEA模块(module)的概念和使用_对比Eclipse
- python笔记30-docstring注释添加变量
- Taro+react开发(100):问答模块07适配
- Windows GDI和GDI+编程实例剖析(1)
- 零基础带你学习MySQL—自连接(二十一)
- Google 已经实现即点即玩,国内 Android 何时跟上?
- php相册上传和删除吗,php上传与删除图片的简单范例
- ubuntu18.04窗口截图和选区截图快捷键
- 谷歌中国发布三国赤壁地图
- 2021全国特种设备-R1快开门式压力容器充装模拟考试题库一[安考星]
- 微信小程序存在的风险_微信小程序交易存在哪些风险
- 合宙Air724 Luat 开发接入ThingsCloud 物联网云平台
- 给高特键轴开盖的操作技巧
- IT实习生需要做什么?IT实习心得
- window系统换为ubuntu系统
- Vue3源码阅读指南——计算属性(effectcomputed)
- oracle官网下载教程
热门文章
- 现代循环神经网络-1.门控循环单元(GRU)【动手学深度学习v2】
- javaweb汽车租赁系统springboot+vue+nodejs
- ubuntu 16.04 + eigen3 安装
- requests.exceptions.ChunkedEncodingError: (‘Connection broken: IncompleteRead(0 bytes read)‘, Incomp
- 改编的一个屏幕保护程序
- hutool 解读(三)—— IO流
- 【调音小栈】普瑞声纳Revelator io24直播关联机架驱动跳线设置教程
- PHP源生数据分页显示
- Android 沉浸式模式
- 基于simulink的离散系统