C++-牛场主的烦恼(进击的奶牛) 解题思路
【Horn Studio】编程专栏: 牛场主的烦恼 解题思路
更新:转战TinyMCE5编辑器,界面可能稍有不同。体面转换为Luogu
题目
题目描述
Farmer John 建造了一个有 NN(22 \le≤ NN \le≤ 100000100000) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 x_1x1 ,...,x_NxN (0 \le≤ x_ixi \le≤ 10000000001000000000)。
他的 CC(22 \le≤ CC \le≤ NN) 头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?
输入格式
第 11 行:两个用空格隔开的数字 NN 和 CC。
第 22 ~ N+1N+1 行:每行一个整数,表示每个隔间的坐标。
输出格式
输出只有一行,即相邻两头牛最大的最近距离。
输入输出样例
5 3
1
2
8
4
9
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)快来看看了!做对了我叫你爸爸!