欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POJ3258 River Hopscotch(二分+贪心)

程序员文章站 2024-03-17 15:26:28
...

题目:
River Hopscotch
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 13858 Accepted: 5889
Description

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).
Source

USACO 2006 December Silver
[Submit] [Go Back] [Status] [Discuss]

思路

先说题目的意思:
有一条河,它的宽度是L,在河里面垂直分布着N个石头,现在有一个奶牛要过河,养牛的人想要锻炼一下奶牛的跳跃能力,于是要在这些石头中,去除M个石头,求去除后的石头中相邻石头的距离中最大的值是多少

用样例来说明一下,样例中河的长度是25,里面有5个石头,现在要去除2个石头。
我们用数组dis[]来表示每一个石头与起点的距离,dis[0]和dis[6]来表示起点和终点

dis[0] dis[1] dis[2] dis[3] dis[4] dis[5] dis[6]
0 2 11 14 17 21 25

要去除两个,题目里去除了2和14
那么

dis[0] dis[1] dis[2] dis[3] dis[4]
0 11 17 21 25

去除后,石头的相邻距离分别为:11,6,4,4
很明显,4是最小的,所以样例的结果是4


现在来说这个题的做法:
我们先对石头们排个序,然后采用二分的策略
现在的假设是mid为我们要求相邻距离中的最小值,cnt代表当前mid为最小值时,要去掉的石头的数量
继续以样例来说明

  1. 从0-25,mid=12,那么我们遍历一遍这些石头,如果dis[i]-dis[last]<=mid,也就是如果石头相邻的距离比我当前假设的最小的距离还要小,我们就要把这个石头删除掉(为了保证mid最小),如果dis[i]-dis[last]>mid,那么就符合条件,我们把last指针移到当前遍历的石头上面
  2. 经过循环以后有一个cnt值,是我们要删除的石头的数量,现在跟题目中要删除的石头的数量作比较,如果cnt>k那么就证明我们删除的多了,所以我们要二分从区间的左边的部分找,也就是end=mid-1,反之我们要二分从区间的右边部分找,start=mid+1,最后返回start,具体看代码

    代码

#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<iostream>
#include <cmath>
#include<stack>
#include<queue>
#include<vector>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 10000007
#define debug() puts("what the fuck!!!")
#define N (1010)
#define ll long long
using namespace std;
int dis[60000];
int l,n,m;
int solve(int start,int end,int k)
{
    int cnt,last,mid;
    while(start<=end)
    {
        cnt=last=0;
        mid=(start+end)>>1;//mid为当前的最小距离的最大值
        for(int i=1; i<=n+1; i++)
        {
            if(dis[i]-dis[last]<=mid)//dis[i]-dis[last]代表当前两块石头的距离
                cnt++;//cnt代表要去掉的石头的数量
            else
                last=i;//执行到这一步,就证明这一个石头不用去除,所以要计算后面的d[i]-d[last]的时候需要更新last
        }
        if(cnt>k)
            end=mid-1;
        else
            start=mid+1;
    }
    return start;
}

int main()
{
    scanf("%d%d%d",&l,&n,&m);
    dis[0]=0,dis[n+1]=l;
    for(int i=1; i<=n; i++)
        scanf("%d",&dis[i]);
    sort(dis,dis+n+1);
    printf("%d\n",solve(0,l,m));
    return 0;
}