进击的奶牛

题面(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原创**

猜你喜欢

转载自blog.csdn.net/c_uizrp_dzjopkl/article/details/83342674