题目大意:一群牛要过河,河中有许多石墩,FJ为了锻炼牛的跳跃力,将其中的m个石墩摘掉,求所有情况中最大的跳跃最小值。

 

思路:用一个变量sum累加,跳跃值mid通过二分来枚举。

(1)如果可以摘除的石墩超过m的话,说明牛的跳跃值太大了,并不是最小跳跃值。

(2)如果可以摘除的石墩刚好等于m的话,也不一定是最小的。

(3)如果小于m的话,说明mid偏小。

 

CODE:

 

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int SIZE = 50010;
int high_bound, low_bound;

int a[SIZE];
int L, m, n;


int BSearch(int x, int y, int m)
{
    while(x <= y)
    {
        int mid = x+(y-x)/2;
        int block = 0, sum = 0;
        for(int i = 1; i <= n+1; i++)
        {
            if((sum+=a[i]-a[i-1]) <= mid)    block++;   //看是否连续的拿走石子,注意是sum+=a[i]-a[i-1] 
            else sum = 0;
        }
        if(block <= m) x = mid+1;      //当block == m时,但不一定是最小的,<m说明跳跃值偏小。 
        else y = mid-1;
    }
    return x;
}



int main()
{
    while(~scanf("%d%d%d", &L, &n, &m))
    {
        low_bound = 0x3f3f3f3f;           //跳跃的最小距离 
        high_bound = L;                   //跳跃的最大距离 
        a[0] = 0;    a[n+1] = L;
        for(int i = 1; i <= n; i++)    scanf("%d", &a[i]);
        sort(a, a+n+2);
        for(int i = 1; i <= n+1; i++)
        {
            low_bound = min(low_bound, a[i]-a[i-1]);
        }
        int ans = BSearch(low_bound, high_bound, m);
        printf("%d\n", ans);
    }
    return 0;
}

 

posted on 2012-09-04 10:47  有间博客  阅读(980)  评论(0编辑  收藏  举报