二分思路:这是一道典型的二分答案的题目,题目中要求的:求最短跳跃距离的最大值,就是典型二分答案,题目已经给出了二分答案的两个条件:单调性和有界性,单调性就是石头之间的距离是单调递增的,并且给出了他们的起点与终点,我们可以在这一段距离内进行二分答案,然后在check函数中判断我们每次跳跃的距离,假设我们现在二分的答案是正确答案,如果前后两个石头的距离小于我们二分的答案,那么我们就要将他移除,否则就可以跳过这一块石头,最后我们在判断一下移除的石头是不是大于了输入的最大移除数:
如果是的话,返回false,因为我们的这个二分答案开大了,所以会导致很多石头都符合移除的条件,我们将右边界赋值为mid-1,
否则如果移除的石头小于等于我们二分出来的答案,那么这个答案可能就是当前的最优解,因为它没有超过最大的移除数,然后我们再在它的右边继续寻找最短跳跃距离的最大值
(最短跳跃距离的最大值):就是我们在不超过最大移除数的情况下,所能二分到的最短最大跳跃距离,超过这个距离,我们移除的石头就会超过输入的最大值
上代码
#include<bits/stdc++.h>
using namespace std;
int d,n,m,mid,ans,l,r;
int a[55555];
bool check(int x){
int tot=0,now=0;
for(int i=1;i<=n;i++){
if(a[i]-a[now]<x)tot++; //如果小于我们二分的答案,我们就移走他
else now=i;
}
if(tot>m) return false;
else return true;
//如果移走的石头大于我们的最大移除数,那么它和他右边的所有数都是非法的
//否则它就是当前的最优解,并且我们在它的右边继续寻找更大的解
}
int main(){
cin>>d>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
a[n+1]=d;
l=1,r=d;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))l=(ans=mid)+1; //当前的数是最优解,并且在它的右边去寻找更优解
else r=mid-1; //它右边的都是非法解,我们直接将边界拉到mid-1的位置寻找更小的解
}
cout<<ans; //输出答案
return 0;
}