C++-牛场主的烦恼(进击的奶牛) 解题思路

【Horn Studio】编程专栏: 牛场主的烦恼 解题思路

更新:转战TinyMCE5编辑器,界面可能稍有不同。体面转换为Luogu

题目

题目描述

Farmer John 建造了一个有 NN(2\le≤ N\le≤ 100000100000) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 x_1x1 ,...,x_NxN (0 \le≤ x_ixi \le≤ 10000000001000000000)。

他的 CC(2\le≤ C\le≤ NN) 头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

输入格式

第 11 行:两个用空格隔开的数字 NN 和 CC。

第 22 ~ N+1N+1 行:每行一个整数,表示每个隔间的坐标。

输出格式

输出只有一行,即相邻两头牛最大的最近距离。

输入输出样例

输入 #1
5 3
1 
2 
8 
4 
9 
 
输出 #1
3

思路

这道题目同样是是用二分法来做,但是由于需要写出来判断是否合法,所以就需要在代码中加入一个判断程序是否合法的函数,就像这样:

bool check(int x)//判断这一组排列是否合乎情理
{
    int tmp = a[1] + x;//贪心((从左到右能选则选))验证
    int sum = 1;
    for (int i = 2; i <= n; i++) {
        if (a[i] >= tmp) {
            sum++;
            tmp = a[i] + x;
        }
    }
    return sum >= m;//m代表的是牛的头数
}

 

通俗来讲,这个问题就是求满足 C(d)的最大的 d,另外,最近的间距不小于 d 也可以说成是所有瓶盖的间距都不小于 d,因此就有 C(d)表示可以安排瓶盖的位置使得任意的两个瓶盖的距离不小于 d。
这个问题的判断使用贪心+二分法便可非常容易地求解。
    1.对瓶盖的位置 x 进行排序
    2.把第一个瓶盖放入 x0 的位置
    3.如果第 i 个瓶盖放入了 xj 的话,第 i+1 个瓶盖就要放入满足 xj+d≤xk 的最小的 xk 中

这基本上就是check函数的解释。

接下来加上二分法的基本模块就可以完成,中间把判断条件改成check(x)便行。

代码

标准代码,请勿抄袭!

#include <bits/stdc++.h>
using namespace std;
int n, m, l, r, mid;
int a[1000001];

bool check(int x)
{
    int tmp = a[1] + x;
    int sum = 1;
    for (int i = 2; i <= n; i++) {
        if (a[i] >= tmp) {
            sum++;
            tmp = a[i] + x;
        }
    }
    return sum >= m;
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    sort(a + 1, a + 1 + n);
    l = 0, r = a[n] - a[1];
    while (l <= r) {
        mid = (l + r) / 2;
        if (check(mid))
            l = mid + 1;
        else
            r = mid - 1;
    }
    cout << r;
    return 0;
}

彩蛋

走过路过瞧一瞧了!冯子坤最新出的题目T235956 高精度计算器(高精度-进阶) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)快来看看了!做对了我叫你爸爸!

posted @ 2022-04-24 18:27  冯子坤  阅读(176)  评论(0编辑  收藏  举报