第1部分 基礎算法(提高篇)--第2章 二分與三分-1433:【例題1】憤怒的牛

1433:【例題1】憤怒的牛

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 2091 通過數: 1201
【題目描述】
農夫 John 建造了一座很長的畜欄,它包括N(2≤N≤100,000)個隔間,這些小隔間依次編號爲x1,…,xN(0≤xi≤1,000,000,000). 但是,John的C(2≤C≤N)頭牛們並不喜歡這種佈局,而且幾頭牛放在一個隔間裏,他們就要發生爭鬥。爲了不讓牛互相傷害。John決定自己給牛分配隔間,使任意兩頭牛之間的最小距離儘可能的大,那麼,這個最大的最小距離是什麼呢

【輸入】
第一行:空格分隔的兩個整數N和C;

第二行—第N+1行:i+1行指出了xi的位置。

【輸出】
一個整數,最大的最小值。

【輸入樣例】
5 3
1 2 8 4 9
【輸出樣例】
3
【提示】
把牛放在1,4,8這樣最小距離是3。


思路:
它是求最小值最大的問題。每兩頭牛之間的最小距離爲 d ,也就是每兩頭牛之間的距離 >= d ,問題也就是求這個 d 最大是多少。
1.對所有的牛舍從小到大排序。
2.假設我們把第 i 頭牛放在 ai 號牛舍裏,那麼第 i+1 頭牛就要放在 ai+d<=ak 的ak 牛舍中,由於可能有很多牛舍滿足條件,我們 選取距離 ai 最近的一個(這是很顯然的,因爲這樣對後面的選擇影響小),然後依次類推,放牛。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>

using namespace std;

const int maxn=1e5+1;
int n,c;
int a[maxn];

bool check(int d)    
{
    int cow = 1;//我們放了第一個cow
    int now = a[1]+d;//下一個cow就要放到>=的牛舍裏距離上一個cow最近的牛舍中了
    for(int i = 2;i <= n;i++)//for循環,計算可以放入cow的數目
    {
        if(a[i] < now) continue;
        cow++; //放進一頭牛 
        now = a[i]+d;//找下一個牛舍應符合的條件 
    }
    return cow >= c;//判斷是否夠c個
}

int main()
{
    scanf("%d%d",&n,&c);
    for(int i = 1;i <= n;i++)
       scanf("%d",&a[i]);     
    
    sort(a+1,a+n+1);      //輸入數據,然後排序一下牛舍
    
    int l = 0,r = a[n]-a[1];  //初始化一下 L 爲0,r 其實就是最後的結果,初始化爲第一個牛舍與最後一個牛舍的距離
    while(l<=r)
    {
        int mid = (l+r)>>1;  //mid爲暫定的那個最小距離d,二分(l+r)÷2
        if(check(mid)) l = mid+1;  //最小距離定爲這個mid,cow可以放下的數目>=規定數目,那麼說明這個mid可以再大一點, 更新 l 
        else r = mid-1; //最小距離定位這個mid,牛舍不能放下牛,那就說明這個距離就要縮小一點,更新 r 
    }
    
    printf("%d",r);
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章