1. 程式人生 > 其它 >憤怒的牛(貪心策略(二分策略))

憤怒的牛(貪心策略(二分策略))

二分策略

Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).
His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

* Line 1: Two space-separated integers: N and C
* Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

* Line 1: One integer: the largest minimum distance

Sample Input

5 3
1
2
8
4
9

Sample Output

3

翻譯:

描述

農民約翰建造了一個新的長谷倉,有N(2<= N<= 100,000)攤位。攤位位於 x1,...,xN 位置的直線上(0 < = xi < = 1,000,000,000)。
他的C(2<= C <= N)奶牛不喜歡這種牛舍佈局,一旦被放進牛舍,就會變得相互攻擊。為了防止奶牛互相傷害,FJ希望將奶牛分配到牛舍,以便它們之間的最小距離儘可能大。最大最小距離是多少?

輸入

* 第 1 行:兩個空格分隔的整數:N 和 C
* 第 2 行..N+1:第 i+1 行包含一個整數停滯位置 xi

輸出

* 第 1 行:一個整數:最大最小距離

分析:

1. 找“最大最小距離”或者“最小最大距離”時,用二分策略

2. 二分策略:bool型別,判斷在總距離內的多少距離能成功,即二分查詢,如果不能成功則right=middle-1(縮小),如果成功則left=middle+1(放大),這樣就能找到最大的可行距離。

      二判定多少距離能成功需要構建bool函式,可以換一種思路,先確定第一隻牛在最左邊,依次在>=distance的屋子裡放第二隻牛,接著在距離第二隻牛>=distance的屋子放第三隻......此役類推如果能         放m只,則表示可行,返回true。

解答:

/*
-------------------------------------------------
   Author:       wry
   date:         2022/3/1 17:10
   Description:  test
-------------------------------------------------
*/

#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 1e5+10;

int roof[MAXN];

bool Judge(int n,int m,int distance) {    //在n個屋子,m頭牛的情況下,是否能夠滿足最大最小距離(級每個之間的距離都)大於distance
    int location = roof[0];     //第一個牛在第一個屋子
    int number = 1;
    for (int i=1;i<n;i++) {
        if (roof[i]-location>=distance) {
            location = roof[i];
            number++;
            if (number==m) {
                return true;
            }
        }
    }
    return false;
}

int main() {
    int n,m;    //n個物資,m頭牛
    cin >> n >> m;
    for (int i=0;i<n;i++) {
        cin >> roof[i];
    }
    sort(roof,roof+n);    //升序

    //對distance進行二分
    int left = 1;     //最小間距為1
    int right = roof[n-1]-roof[0];    //最大間距(也就是最後的解)為首尾之差,如9-1=8
    while (left<=right) {
        int middle = left + (right -left)/2;
        if (Judge(n,m,middle)) {    // 如果可以滿足,則繼續放大一下distance
            left = middle+1;
        }
        else {    //如果不能滿足,則縮小distance
            right = middle-1;
        }
    }     //直到某次可以,然後left=middle+1,使得left==right==middle,此時如果成功,right就是答案,如果不成功,right=middle-1也就是剛剛成功的left,返回right就是正確答案
          //在某次不可以,然後right=middle-1,使得left==right==middle,此時如果成功,right就是答案,如果不成功,right=middle-1也就是剛剛成功的left,返回right就是正確答案

    cout << right << endl;
}