1. 程式人生 > >River Hopscotch (最大化最小值)

River Hopscotch (最大化最小值)

每年,奶牛都會舉辦一場特別版的跳房子活動,其中包括在河中小心翼翼地從岩石跳到岩石。興奮發生在一條長而直的河流上,開始時有一塊岩石,最後有另一塊岩石,距離開始L單位(1≤L≤1,000,000,000)。沿著起始岩石和結束岩石之間的河流,出現N(0≤N≤50,000)更多的岩石,每個岩石從起點開始的整數距離Di(0 <Di <L)。

為了玩遊戲,每頭母牛依次從起始岩石開始,並嘗試到達終點岩石的終點,只從岩石跳到岩石。當然,不那麼靈活的奶牛永遠不會進入最後的岩石,而是最終進入河中。

農民約翰為他的奶牛感到驕傲,每年都會觀看這次活動。但隨著時間的推移,他厭倦了看著其他農民的膽小的奶牛蜷縮在距離太近的岩石之間的短距離。他計劃移除幾塊岩石,以增加牛必須跳到最後的最短距離。他知道他無法移除起始和結束的岩石,但他計算出他有足夠的資源去除M岩石(0≤M≤N)。

FJ想知道在他開始移除岩石之前他能增加最短距離*的確切程度。幫助農夫約翰確定在移除最佳M岩石後,母牛必須跳躍的最大可能最短距離。

輸入
第1行:三個以空格分隔的整數:L,N和M.
第2行...... N + 1:每一行包含一個整數,表示某些岩石遠離起始岩石的距離。沒有兩個岩石共享相同的位置。
產量
第1行:一個整數,是除去M岩石後母牛必須跳躍的最短距離的最大值

題目大意:加上起點和中點兩個點 ( N+2) 從中減去M個點使所有間隔中的最小值最大化;

用到二分法

二分模板:

    while (r-l>1)
    {
       mid=(l+r)/2;
      if(finds(mid)<=m)   //(根據題意變換)
        l=mid;            //儲存目前最合適的點
      else
        r=mid;
    }
    cout <<l<<endl;      //輸出那個最終最合適的點

AC 程式碼:

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

int L;
int n,m;
int arr[100000];
int finds(int mid)                 //find 函式是判斷mid是否為合適的點
{   int next=1;
    int k=0;
    int nowpost=arr[0];
    while (next<=n+1)
    {
        while (nowpost+mid>arr[next]&&next<=n+1)    //mid既然是最小值,就不允許存在mid還小的arr[next]作為nowpost和nowpost+mid
        {                                           //的中間值;
            k++;
            next++;
        }
        nowpost=arr[next];
        next++;
    }
    return k;
}
int main()
{
    cin >>L>>n>>m;
    arr[0]=0;
    arr[n+1]=L;

    for(int i=1;i<=n;i++)
    cin >>arr[i];
    sort(arr,arr+n+2);

    int l=0;
    int r=2*L;            //防止最小值是L的情況
    int mid;              //mid被認為是當前最小值去測試
    while (r-l>1)
    {
       mid=(l+r)/2;
      if(finds(mid)<=m)   //(根據題意變換) 不斷尋找最大化最小值的mid
        l=mid;            //找到一個滿足條件繼續找最大值
      else
        r=mid;
    }
    cout <<l<<endl;

    return 0;
}