题目背景
一年一度的“跳石头”比赛又要开始了!
题目描述
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 NN 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 MM 块岩石(不能移走起点和终点的岩石)。
输入输出格式
输入格式:
第一行包含三个整数 L,N,ML,N,M ,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1L≥1 且 N≥M≥0N≥M≥0 。
接下来 NN 行,每行一个整数,第 ii 行的整数 Di(0<Di<L)Di(0<Di<L) , 表示第 ii 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
典型的贪心问题, 求最短距离最大值, 但我一开始抉择的方向弄反了.
首先要求的是最短距离最大值, 只是一个upper_bound的问题.
若当前距离可以的话, 就要去考虑更大的值.
若当前距离不可以的话, 就要去考虑最小的值.
// P2678 跳石头
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
const int MAXN = 5e4 + 600;
typedef long long ll;
using namespace std;
int l, n, m;
int stone[MAXN];
bool judge(int limit){
ll lastPos = 0;
int counter = m;
for(int i = 0; i < n; ++i){
if(stone[i] - lastPos >= limit){
lastPos = stone[i];
}
else{
if(counter-- == 0){
return false;
}
}
}
if(l - lastPos < limit){
return false;
}
return true;
}
int main(){
// printf("%lld\n%lld\n", 0x3f3f3f3f, 1000000000);
scanf("%d%d%d", &l, &n, &m);
for(int i = 0; i < n; ++i){
scanf("%d", stone + i);
}
int lo = 0, mi, hi = 0x3f3f3f3f;
int half;
int length = hi - lo;
while(length){
half = length >> 1;
mi = lo + half;
if(judge(mi)){
lo = mi + 1;
length = length - half - 1;
}
else{
length = half;
}
}
printf("%d\n", lo - 1);
return 0;
}