题面(from luogu)
进击的奶牛
Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚,这些隔间分布在一条直线上,坐标是x1,…,xN (0<=xi<=1,000,000,000)。
他的C(2<=C<=N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?
输入格式:
第1行:两个用空格隔开的数字N和C。
第2~N+1行:每行一个整数,表示每个隔间的坐标。
输出格式:
输出只有一行,即相邻两头牛最大的最近距离。
输入样例#1:
5 3
1
2
8
4
9
输出样例#1:
3
题目分析
这是一到可以很容易看出来的二分题(巨大的查找范围可以看出)。
在正常情况下,二分模板都是可以套进去的,但是难点是在对解是否合法的判断上。
在这一道题目上面,我们可以写一个子程序来判断一下,具体的也就是用当前的解,不停的向前面放,如果当前的放不了了,就说明有一个屋子废了,当然,我们算出最多可以废几个屋子,对比一下,即可
到这里,这一道题就写完了,
其他的也就是套模板了,这一题是比较适合用while版的二分来写的
代码
#include <bits/stdc++.h>
using namespace std;
int a[1000009],n,k;
bool judge(int x) //判断函数
{
int sum = 0; //当前一个屋子都没有废,
int now = a[1]; //从第一个开始试
for (int i = 2; i <= n; i++)
{
if (now + x > a[i]) sum++; //判断当前的是否合法,也就是当前试了这组解后有没有占到后面的房子里,如果有了,这一组就废了,当前的得放在后面后面
else //反之,可以放,继续向前放
now = a[i]; //这是下一个的起点
if (sum > n - k) return false; //判断是否还有房子可以浪费,没有了,就说明,这组解,不合法的
}
return true; //反之就是合法的
}
int main()
{
cin>>n>>k;
for (int i = 1; i <= n; i++) cin>>a[i]; //输入
sort(a+1,a+n+1); //数据必需有序的
int left = 1; //左界
int right = a[n] - a[1]; //右界
while (left <= right)
{
int mid = (left + right) / 2; //去中间数
if (judge(mid)) left = mid + 1; //如果这是一组合法的解,我们就像前试探一下,看一看有没有更优秀的
else //反之
right = mid - 1; //这一组解不合法,就说明偏大了,向前去找
}
if (judge(right)) cout<<right; //判断更优秀的解
else
cout<<left;
return 0; //完美的结束程序
}
** 菜鸡c_uizrp_dzjopkl原创**