noip 2015 跳石头
思考了许久 最终挑了如下一篇题解给自己解答
#include<cstdio>
#include<cstring>using namespace std;
const int maxn=50010;
//n,m,L的意义和题目描述中的一样,a[]表示每个石头到起点的距离,方便起见,将终点补充为最后一块石头
int n,m,L;
int a[maxn];
//二分了最短跳跃距离 mid之后,开始检查这个答案mid能不能满足至多抽走m块石头
bool check(int mid){
//last表示上一块没有被抽走的石头离起点的距离
int last=0,cnt=0;
for(int i=1;i<=n;i++){
//如果两点之间的距离比跳跃距离短,那么就需要把这一块石头拿走,不然的话就可以不用管。
//当然如果i==n也就是终点的时候是不能拿走终点的,但是这个时候拿掉前一个石头也一定能达成目的,所以不管怎样只需要拿掉一个石头。
//如果不用拿掉的话,上一块没有抽走的石头就是当前这一块了。
if(a[i]-last<mid) cnt++;
else last=a[i];
}
//如果必须要拿掉的石头数目<=m个,说明二分出的最短距离可以接受,返回true
if(cnt<=m) return true;
return false;
}
int main(){
int ans;
scanf("%d%d%d",&L,&n,&m);
n++;a[n]=L;
for(int i=1;i<n;i++) scanf("%d",&a[i]);
int l=0,r=a[n],mid;
while(r-l>1){
mid=(l+r)>>1;
//如果这个值可以接受,那么比它小的值都可以接受,二分的下界就可以变成这个新的值
//如果不能接受,那么比它大的值也不能接受,二分的上界变成这个新的值
if(check(mid)) l=mid;
else r=mid;
}
//当然如果最后区间还剩下两个的时候,有可能上界也是可以接受的。[其实这种情况只发生在a[n]为最大距离时]
if(check(r)) ans=r;
else ans=l;
printf("%d",ans);
return 0;
}