题目描述:
一年一度的“跳石头”比赛又要开始了!
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有n 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走m 块岩石(不能移走起点和终点的岩石)。
输入格式:
输入文件第一行包含三个整数 ,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。
接下来 n 行,每行一个整数,第 i 行的整数 d[i](0 < d[i] < l)表示第 i 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同 一个位置。
输出格式:
输出文件只包含一个整数,即最短跳跃距离的最大值。
样例
样例输入
复制25 5 2
2
11
14
17
21
样例输出
复制4
数据范围与提示
对于 20% 的数据,0<=n<=m<=10。int check(int p) {
int b = 0, c = 0;
for (int i = 1; i <= n; i++) {
if (a[i] - c < p)
b++;
else
c = a[i];
}
return b;
}
对于 50% 的数据,0<=m<=n<=100。
对于 100% 的数据,0 <=m<=n<=50000,1<=L<=1000000000。
解法如下:
首先,暴力只能的50分。
所以,只能用二分算法去找答案。 *所有二分都是枚举答案!!!
二分算法(也叫分治算法)原理由下👇
现在联系到此题,枚举最短跳跃的距离最大值。
来写check():
int check(int p) {
int b = 0, c = 0; //b是要移走的块数
for (int i = 1; i <= n; i++) {
if (a[i] - c < p) //判断如果距离不够,需移走的块数加1
b++;
else
c = a[i];
}
return b;
}
再加上输入输出:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n, m, l;
LL a[50010];
int check(int p) {
int b = 0, c = 0;
for (int i = 1; i <= n; i++) {
if (a[i] - c < p)
b++;
else
c = a[i];
}
return b;
}
int main() {
scanf("%d%d%d", &l, &n, &m); //输入
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
LL le = 0, ri = l; //设置左右端点
while (ri > le) {//如果没找到答案,就继续找,直到le > ri为止
LL mid = (ri + le + 1) >> 1; //求中间值
if (check(mid) <= m) {
le = mid;
} else {
ri = mid - 1;
}
}
printf("%d", le);
return 0;
}
运行一下样例:
再提交一下: