POJ - 3258 River Hopscotch(二分法求最大化最小间隔)

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 ≤ M ≤ N).

FJ wants to know exactly how much he can increase the shortest distance before he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input
Line 1: Three space-separated integers: L, N, and M
Lines 2.. N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.
Output
Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks
Sample Input
25 5 2
2
14
11
21
17
Sample Output
4
Hint
Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).

题意:在一个宽L的河上,有N个石头,现在牛要踩这些石头跳到对岸,给出每个石头的坐标,问,去掉M个石头后,剩下的石头两两之间的距离最小值,最大能是多少。

对于最大化最小值问题,我们可以用二分解决。首先要求的是最小间隔的值,那么就二分距离来得到符合条件的最小间隔。首先我们确定一个概念:落脚点。我们有N个石头,从中去掉M个,那么有N-M个石头是留下的,这N-M个石头,是牛渡河必须踩到的石头,对于这些石头,我们要保证符合的条件是必须都大于或等于最终求得的结果,间隔最小值。

明白了这个概念,就可以得到二分的条件。首先,我们取一个左边界0到右边界河宽,这一段二分的范围,从中取得一个中值,这个中值即我们设的结果,现在要做的是判断该结果是否符合题目要求的条件。

首先起点是肯定要走的,也就是0的坐标位置,从该点出发,跳向第一个石头,计算第一个石头和第一个落脚点之间的距离,若小于二分得到的最小值,说明在设定的这个最小值情况下,我们正在遍历的这块石头是没有用的,因为其在的位置,使我们设的最小值变小了,我们已经明确一个最小值,那么不应该有任何一个间距小于这个最小值,因此,一旦出现小于最小值的间距,说明某个石头是不应该存在的,是应该被删掉的。此时记录一个cnt表示该最小值下被删除的石头个数。当我们遍历到一个石头,发现其离落脚点的距离大于等于最小值时,说明该石头应该被保留,保留的石头我们要踩上去,因此出现这样的石头时,我们更新落脚点,拿新的落脚点再去衡量后面的石头,与新落脚点的距离是否符合大于等于最小值的条件。

最后遍历玩所有石头,会得到该间距下被删除的石头个数,用于比较题目给出的M个石头。若cnt大于M,说明石头被删多了,那么这个所谓的最小间距,其实是偏大了的,它使得一些不该被删掉的石头也删掉了,因为这个过大的间距,一些石头被包含其中。因此,我们要作出的调整是向较小的方向二分寻找正确答案。

这就是二分的判断条件,即石头被删个数的比较。

若cnt小于M,说明该所谓的最小间隔太小了,一些石头本该被删掉,因为其位置分割了一些间距 。一些石头可以被拿掉却仍在阻碍我们扩大最小间距。因此此时向较大值方向二分查询正确答案。

若cnt等于M,我们同样应增大查找范围,因为这种情况,虽然删掉的石头够数了,但是具体删掉哪些石头呢?我们如果再加大最小间距,那么就是在相同删除石头的数量下,尽量删去排列较为密集的石头,以达到消灭过小的间距的目的。

这样以落脚点的方式,不断筛选石头,用间隔淘汰石头,用淘汰石头的数量判断间隔,得以二分出最大化的最小间隔

#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=5e4+10;
int n,l,m,a[maxn];
bool judge(int mid)
{
    int start=0;
    int cnt=0;
    for(int i=0;i<n;i++)
        if(a[i]-start<mid)cnt++;
        else start=a[i];///理论上还应判断终点与最后一个落脚点的距离要大于最小值,但是题目并没有卡这个问题
    if(cnt>m)return false;
    return true;
}
int main()
{
    while(scanf("%d%d%d",&l,&n,&m)!=EOF)
    {
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        sort(a,a+n);
        int ll=0,rr=l,ans=0;
        while(ll<=rr)
        {
            int mid=(ll+rr)>>1;
            if(judge(mid))
            {
                ll=mid+1;
                ans=mid;
            }
            else rr=mid-1;
        }
        printf("%d\n",ans);
    }
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值