经典例题---跳石头
题目描述
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 NNN 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 MMM 块岩石(不能移走起点和终点的岩石)。
输入输出格式
输入格式:第一行包含三个整数 L,N,ML,N,ML,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1L \geq 1L≥1 且 N≥M≥0N \geq M \geq 0N≥M≥0。
接下来 NNN 行,每行一个整数,第 iii 行的整数 Di(0<Di<L)D_i( 0 < D_i < L)Di(0<Di<L), 表示第 iii 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
输出格式:一个整数,即最短跳跃距离的最大值。
数据范围
0≤ M ≤ N ≤ 50000
1 ≤ L ≤ 10000000000 ≤ M ≤ N ≤ 50000
1 ≤ L ≤ 1,0000000000 ≤ M ≤ N ≤ 50000
1≤ L ≤ 1000000000
类似求 最大值的最小值 最小值的最大值,都可以用二分答案来做。
这其实是一个暴力。暴力枚举检索答案,只不过在暴力枚举的时候,采用了二分优化,使得复杂度降低
这道题是一个二分入门 比较简单 这个二分答案吧 还是很有用的 思想要多理解
代码及注释
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=1e5+7;
int a[maxn],l,n,m;
bool check(int dis){//检测答案是否符合题意
int conut=0,last=0;
for(int i=1;i<=n;i++){
if(a[i]-last<dis)conut++;//和前一个的距离小于dis的 就要移走
else last=a[i];
}
if(conut>m)return false;//移动不能超过m次
else return true;
}
int main(){
scanf("%d%d%d",&l,&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int L=0,R=l,ans=0;
while(L<=R){//二分查找答案 对于每一个答案 检测是否符合题意
int mid=(L+R)/2;
//满足题意的答案 我们继续往右找 因为这个题要找的是最小值的最大值
if(check(mid))L=mid+1,ans=mid;
else R=mid-1;
}
printf("%d\n",ans);
return 0;
}