牛场主的烦恼

题目描述

Farmer John建造了一个有N个隔间的牛棚,这些隔间分布在一条直线上,坐标是x1,...,xN。

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

输入

第1行:两个用空格隔开的数字N和C。
第2~N+1行:每行一个整数,表示每个隔间的坐标

输出

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

样例输入:

5 3
1 
2 
8 
4 
9

样例输出:

3

思路:

(这道题才是值得写博客的题目啊!!!)

这题我们输入的时候,先将l(左边界)赋值为0,r(右边界)在输入的时候取坐标最大值。输入完后,将数组进行排序sort。

接下来就是重头戏————二分,二分的时候,我们该枚举什么呢?显而易见,我们就是要枚举这个最近距离,但是要记住,要从小开始枚举,至于为什么,读者可以自行思考

但是二分的时候该怎么判断这个mid是否可行呢?

我们可以这样,用一个last记录上一个牧场的位置,每次判断当前牧场与上一个牧场的距离是否超过了枚举的mid,如果 ≥ ,我们就可以放一只牛在这里,如此循环反复下去,到最后的时候,判断放的牛的总数是否等于总的牛的数量(第一牛是固定在第一个牧场)
(这个做法是有单调性的哟,可以自行思考)

那么这个做法用的是什么呢?就是——————贪心

思路也就这么简单,直接上代码!!!

代码:

#include <bits/stdc++.h>
using namespace std;

int room[100005];
int l = 0,r = -1;
int n,c;

bool check (int k){
	int last = -10000000; //这个地方一定要定小一点,之前定小了检查了半天。 
	int s = 0;
	for(int i = 1;i <= n;i++){
		if(room[i] - last >= k){
			s++;
			last = room[i];
		}
		if(s >= c){
			break;
		}//如果满足了,就没有执行下去的必要了可以直接break 
	}
	if(s >= c) return true;
	else return false;
}

void erfen(){
	while(l < r){
		int mid = (l+r+1)/2;
		if (check(mid)){
			l = mid;
		}
		else{
			r = mid - 1;
		}
	}//二分 
}

int main(){
	scanf("%d%d",&n,&c);
	for(int i = 1;i <= n;i++){
		scanf("%d",&room[i]);
		r = max(r,room[i]);
	}
	sort (room + 1,room + n + 1);
	//不要忘记排序!!! 
	
	erfen();
	
	printf("%d",l);
	return 0;
}
posted @ 2022-04-23 21:46  XDFZ武斌  阅读(112)  评论(0)    收藏  举报