2019.11.12 跳石頭

題目背景

一年一度的「跳石頭」比賽又要開始了!ios

題目描述

這項比賽將在一條筆直的河道中進行,河道中分佈着一些巨大岩石。組委會已經選擇好了兩塊岩石做爲比賽起點和終點。在起點和終點之間,有 \(N\) 塊岩石(不含起點和終點的岩石)。在比勝過程中,選手們將從起點出發,每一步跳向相鄰的岩石,直至到達終點。git

爲了提升比賽難度,組委會計劃移走一些岩石,使得選手們在比勝過程中的最短跳躍距離儘量長。因爲預算限制,組委會至多從起點和終點之間移走 \(M\) 塊岩石(不能移走起點和終點的岩石)。spa

輸入格式

第一行包含三個整數 \(L,N,M\),分別表示起點到終點的距離,起點和終點之間的岩石數,以及組委會至多移走的岩石數。保證 \(L \geq 1\)\(N \geq M \geq 0\)code

接下來 \(N\) 行,每行一個整數,第 \(i\) 行的整數 \(D_i( 0 < D_i < L)\), 表示第 \(i\) 塊岩石與起點的距離。這些岩石按與起點距離從小到大的順序給出,且不會有兩個岩石出如今同一個位置。get

輸出格式

一個整數,即最短跳躍距離的最大值。string

輸入輸出樣例

輸入 #1it

25 5 2 
2
11
14
17 
21

輸出 #1io

4

說明/提示

輸入輸出樣例 \(1\) 說明:將與起點距離爲 \(2\)\(14\) 的兩個岩石移走後,最短的跳躍距離爲 \(4\) (從與起點距離 \(17\) 的岩石跳到距離 \(21\) 的岩石,或者從距離 \(21\) 的岩石跳到終點)。class

另:對於 \(20\%\)的數據,\(0 \leq M \leq N \leq 10\)stream

對於\(50\%\)的數據,\(0 ≤ M ≤ N ≤ 100\)

對於 \(100\%\)的數據,\(0 \leq M \leq N \leq 50,000,1 \leq L \leq 1,000,000,000\)

容易想到二分答案。考慮如何\(check\)。貪心地找第一個比須要\(check\)的長度距目前位置距離大的石頭並跳到該處,加上中間跳過的全部石頭做爲答案。

注意在處理終點時,若是終點距離目前點的位置比須要\(check\)的長度小,則上次跳到這裏的行爲時不合法的,應當直接跳過該石頭跳到終點,即答案\(+1\)

上代碼。注意上面那個地方有\(10pts\)分值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cctype>
#define int long long
#define rep(i,a,n) for(register int i=a;i<=n;i++)
#define dep(i,n,a) for(register int i=n;i>=a;i--)
using namespace std;
int l,n,m,d[100050];
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x==0)return;
    write(x/10);
    putchar('0'+x%10);
}
bool check(int len)
{
    int now=0;
    int cnt=0;
    rep(i,1,n-1)
    {
        if(d[i]-now>=len)now=d[i];
        else ++cnt;
        if(cnt>m)return false;
    }
    if(d[n]-now<len)++cnt;
    if(cnt>m)return false;
    return true;
}
signed main()
{
    l=read(),n=read(),m=read();
    rep(i,1,n)d[i]=read();
    d[n+1]=l;
    ++n;
    int ll=1,rr=l;
    while(ll<rr-1)
    {
        int mid=(ll+rr)>>1;
        if(check(mid))ll=mid;
        else rr=mid;
    }
    int ans;
    if(check(rr))ans=rr;
    else if(check(ll))ans=ll;
    write(ans);
    return 0;
}
相關文章
相關標籤/搜索