E - River Hopscotch POJ - 3258(二分)

E - River Hopscotch POJ - 3258

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 ≤ MN).

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

思路

  • 题意:在一个 竖直的河道内有 有 n+2个岩石, 然后又给了我们 出第一块岩石s之后的n+1块岩石距离 s岩石的距离,奶牛们可以从 从起始s的岩石,到终点e岩石,奶牛只能岩石沿着相邻的岩石 跳跃,问当我们从 s 岩石到e岩石之间的n块岩石之间选择的 m块移除后, 奶牛从 s 一路跳到 e 岩石所需的最小跳最大可以是多少.

  • 思路:我们直接用 二分答案,去枚举每一个移除距离,然后如果两块岩石之间的距离小于 我们二分枚举的距离的话,我们就直接把当前这块石头移除,需要注意的是,在移除当前这块石头之后我们,我们还要考虑后面的 石头到 被移除的石头之前的石头的距离是不是也小于我们枚举的 距离 (具体这样的实现 请看代码)

大佬代码

#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn=5e4+10;
int a[maxn];
int n,m,L;
int f(int x)
{
    int l,r;
    l=0,r=1;
    int ans=0;
    while(r<n+2)
    {
        if(a[r]-a[l]<x)//若最后的end都不满足 就把l所在去了,代码没写那个因为效果一样
        {
            r++;
            ans++;
        }
        else
        {
            l=r;
            r++;
        }
    }
    return ans;
}
int solve()
{
    int l=0,r=L,ans,mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(f(mid)<=m)
        {
            ans=mid;
            l=mid+1;
        }
        else
            r=mid-1;
    }
    return ans;
}
int main()
{
    while(~scanf("%d %d %d",&L,&n,&m))
    {
        a[0]=0;
        a[n+1]=L;
        for(int i=1;i<=n;++i)
            scanf("%d",a+i);
        sort(a,a+n+2);
        printf("%d\n",solve());
    }
    return 0;
}

朴素的暴力代码

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

const int Len = 5e5;

int s, n, m;
vector<int> ar;

bool work(int mid, vector<int> br)
{
    int cnt = 0;
    int last = 0;
    for(int i = 0; i < br.size() - 2; )
    {
        int pos = upper_bound(br.begin() + i, br.end() - 1, mid + br[i] - 1) - br.begin();
        cnt += pos - i - 1;
        last = pos - 1;
        i = pos;
    }

    int si = br.size();
    if(si > 2 && last != n && br[n+1] - br[n] < mid)
        cnt ++;
    //cout << mid << " " << cnt << endl;
    return cnt <= m;
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    //freopen("A.txt","r", stdin);
    cin >> s >> n >> m;
    ar.push_back(0);
    int tem;
    for(int i = 1; i <= n; i ++)
        cin >> tem, ar.push_back(tem);
    sort(ar.begin(), ar.end());
    ar.push_back(s);

    int l = 1e9 + 7, r = s;
    for(int i = 1; i <= n+1; i ++)
        l = min(l, ar[i] - ar[i - 1]);

    int mid;
    int ans;
    while(l <= r)
    {
        mid = (l + r) >> 1 ;
        
        if(work(mid, ar))
            l = mid + 1, ans = mid;
        else
            r = mid - 1;
    }
    cout << ans << endl;

    return 0;
}

发布了159 篇原创文章 · 获赞 243 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/105167219