題解: HDU 4004 The Frog's Games (二分搜索)

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):
2513

Problem 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
18

Sample 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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章