题目大意:给出河的宽度L和N块石头,现在要求移除M块石头,使得石头间的距离的最小值达到最大(起点和终点都有一块石头,但这两块石头不能移除)
解题思路:最小值的最大值,肯定用二分了
如果存在最优的距离,那么移走的石头数量肯定刚好是M块的
枚举的时候判断移除石头的数量,只需要从起点开始枚举,然后计算一下在最小跳跃距离内的石头有几个,有几个就移除几个,最后判断移除了多少个石头
如果移走的数量大于M,就表示所枚举的长度偏大
如果移走的数量小于M,就表示所枚举的长度偏小
有一种比较特殊的情况,就是N = M的情况,这种情况下枚举的很多长度都是符合的,但是答案只有一个,那就是L,所以移除数量等于M的时候不代表已经找到解了,应该再长度加1判断一下
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 50010
int pos[maxn], L, N, M;
void init() {
for(int i = 0; i < N; i++)
scanf("%d", &pos[i]);
pos[N++] = L;
pos[N++] = 0;
sort(pos, pos + N);
}
bool judge(int mid) {
int j = 0, cnt = 0;
for(int i = 1; i < N; i++) {
if(pos[i] - pos[j] < mid) {
cnt++;
if(cnt > M)
return true;
continue;
}
j = i;
}
return false;
}
int solve() {
int l = 0, r = L;
int ans = 0x3f3f3f3f;
while(l <= r) {
int mid = (l + r) / 2;
if(judge(mid))
r = mid - 1;
else
l = mid + 1;
}
return l - 1;
}
int main() {
while(scanf("%d%d%d", &L, &N, &M) != EOF) {
init();
printf("%d\n",solve());
}
return 0;
}
时间: 2024-12-23 10:13:50