【NOIP2015】day2_ 跳石頭


題目描述

一年一度的“跳石頭”比賽又要開始了!

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

為了提高比賽難度,組委會計划移走一些岩石,使得選手們在比賽過程中的最短跳躍距離盡可能長。由於預算限制,組委會至多從起點和終點之間移走 M塊岩石(不能移走起點和終點的岩石)。

輸入格式

輸入文件第一行包含三個整數 L,N,M,分別表示起點到終點的距離,起點和終點之間的岩石數,以及組委會至多移走的岩石數。保證 L1 且 NM0

接下來 N行,每行一個整數,第 i 行的整數 Di0<Di<L, 表示第 i 塊岩石與起點的距離。這些岩石按與起點距離從小到大的順序給出,且不會有兩個岩石出現在同一個位置。

輸出格式

輸出文件只包含一個整數,即最短跳躍距離的最大值。

樣例一

input

25 5 2
2
11
14
17
21

output

4

explanation

將與起點距離為 2和 14 的兩個岩石移走后,最短的跳躍距離為 4(從與起點距離 17 的岩石跳到距離 21 的岩石,或者從距離 21 的岩石跳到終點)。

限制與約定

測試點編號 n,m的規模 L的規模
1 n,m10
L10^9
2
3 n,m100
4
5
6 n,m50000
7
8
9
10

時間限制:1s

空間限制:128MB

 

記得這道題是那次聯賽中比較好處理的一道,讓我們求的是最小值中的最大值,顯然是二分枚舉

關鍵就在於對二分出的那個ans的驗證

如果讀懂了題目,不難發現,只要最短距離確定了,因為兩端是定的,所以可以確定必須搬走的石塊,因為要求最小值,所以只要把必須搬走的搬走就好了,其他的隨意

所以只需要O(n)枚舉一次,使得前i個石頭確定不搬,那么需要確定第i+1塊石頭怎么辦,顯然,一旦兩者距離大於了那個最小值就必須把他搬走

所以,時間復雜度是O(n·log(L))

下面附上代碼

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=50005;
int a[maxn],n,m,ans;
bool check(int x)
{
    int sum,last;
    sum=0;last=0;
    for (int i=1;i<=n;i++)
    {
        if (a[i]-last<x) {  sum+=1;continue;}
        last=a[i];
    }//printf("%d\n",sum);
    if (sum>m) return 0;
    return 1;
}
int main()
{
    //freopen("148.in","r",stdin);
    //freopen("148.out","w",stdout);
    int L,R,mid;
    scanf("%d%d%d\n",&L,&n,&m);
    for (int i=1;i<=n;i++) scanf("%d\n",&a[i]);
    n+=1;
    a[n]=L;R=L;
    ans=L=0;
    while (L<=R)
    {   
        mid=L+(R-L)/2;
        if (check(mid)) {  ans=mid;L=mid+1;  }
        else R=mid-1;
    }
    printf("%d",ans);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM