愤怒的牛(贪心策略(二分策略))

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;
}

 

posted @ 2022-03-03 17:07  火星架构师  阅读(271)  评论(0编辑  收藏  举报