The Frog’s Games
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K
(Java/Others) Total Submission(s): 5157 Accepted Submission(s):
2513Problem Description The annual Games in frogs’ kingdom started again.
The most famous game is the Ironfrog Triathlon. One test in the
Ironfrog Triathlon is jumping. This project requires the frog athletes
to jump over the river. The width of the river is L (1<= L <=
1000000000). There are n (0<= n <= 500000) stones lined up in a
straight line from one side to the other side of the river. The frogs
can only jump through the river, but they can land on the stones. If
they fall into the river, they are out. The frogs was asked to jump
at most m (1<= m <= n+1) times. Now the frogs want to know if they
want to jump across the river, at least what ability should they have.
(That is the frog’s longest jump distance).Input The input contains several cases. The first line of each case
contains three positive integer L, n, and m. Then n lines follow.
Each stands for the distance from the starting banks to the nth stone,
two stone appear in one place is impossible.Output For each case, output a integer standing for the frog’s ability
at least they should have.Sample Input
6 1 2
2
25 3 3
11
2
18Sample Output
4
11
题目大意
在一条宽度为l的河上有n个石头, 要求用青蛙最多跳m次过河。 问青蛙最小的跳跃能力是多少。
思路
这个问题用二分查找可以非常容易的求得答。 然我们套用二分搜索的模型试着解答这个问题。
令:
条件C(x):= 可以经过m次长度最长为x的跳跃就可以到达河对岸
现在问题就转化为了求 x 的最小值。 在初始化区间的时候, 只需要将下界初始化为0, 上界初始化为河的宽度即可。
现在的问题是如何高效的判断c(x)是否可行。 由于跳跃长度为x的青蛙每次跳跃的距离等于不大于x的石头的最大的距离
C(x) = (距离当前位置不大于x的最远的石块 m次累加)
代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
int l, n, m;
int sum[500010];
bool fun(int k)
{
int last = 0, front = 1, step = 0;//mark 用front前驱搜索
if (k * m < l)
return false;
while (front <= n + 1)
{
step++;
if (sum[front] - sum[last] > k)
return false;
while (sum[front] - sum[last] <= k && front <= n + 1)
{
front++;//mark
}
last = front - 1;//mark
}
if (step > m)//mark step大于m说明现在的跳跃能力太小 需要增大
return false;
return true;//在step == m 的时候继续缩小 因为我们需要的是符合条件的最小值
}
int main(void)
{
while (scanf_s("%d %d %d", &l, &n, &m) != EOF)
{
memset(sum, 0, sizeof(sum));
for (int i = 1; i <= n; i++)
{
scanf_s("%d", &sum[i]);
}
sum[n + 1] = l;
sort(sum, sum + n + 2);
int i = 0, u = l;
while (i <= u)
{
int mid = (i + u) / 2;
if (fun(mid))
u = mid - 1;
else
i = mid + 1;
}
printf("%d\n", i);
}
return 0;
}