题意:给出河宽,石头数,还有最多可以删去石头的数量m。意思是你要过河,但是你必须踩着石头过河,在这个过程中你可以删去一些石头,最多可以删m个,求跳跃的过程中最小的距离中的最大距离.
思路:区间是0~L ,然后二分mid 代表了最小距离,如果这个距离满足是最小距离(ok函数模拟删除石头的过程)left + 1,否则right - 1,逐渐逼近答案
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 50010;
__int64 rock[maxn];
__int64 L , n , m;
bool ok(__int64 mid) {
int remove = 0;
int i , pos = 0;
for (i = 1 ; i <=n+1 ; i ++) {
if (rock[i] - rock[pos] < mid) {//mid代表跳跃最小距离 比这个距离小的i 删去
remove ++;
if (remove > m) return false;
}
else pos = i;
}
return true;
}
int main() {
int i;
while (scanf("%I64d %I64d %I64d",&L,&n,&m)!=EOF) {
rock[0] = 0;
for (i = 1 ; i <= n ; i ++) scanf("%I64d",&rock[i]);
rock[n+1] = L;
sort(&rock[1],&rock[n+2]);
__int64 left = 0;
__int64 right = L;
__int64 mid;
int ans;
while (left <= right) {
mid = (left+right)>>1;
if (ok(mid)) {ans = mid ;left = mid + 1;}//为什么加个ans 就过 ? 跳出循环的条件 可以是left > right的原因么?
//因为最后如果是left == right 的时候 可能下一步是left = mid + 1,或者是
//right = mid - 1; 所以 用一个变量来记录答案比较好
else {right = mid - 1;}
}
printf("%d\n",right);
}
}