问题描述
Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).
His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
输入
* Line 1: Two space-separated integers: N and C
* Lines 2..N+1: Line i+1 contains an integer stall location, xi
输出
* Line 1: One integer: the largest minimum distance
样例输入
5 3
1
2
8
4
9
样例输出
3
提示
OUTPUT DETAILS:
FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.
Huge input data,scanf is recommended.
个人理解
这个题我已开始看的也云里雾里,它的英文表达太绕了,后来理解一下其实意思就是,按顺序告诉你各个房子的位置,让你尽量分散地把牛放到房子里面去,然后求出尽量分散地情况下,最近的两头牛的距离。
解法
这个题解法不唯一,其实就是一个非常典型的二分查找题,只不过你判断满足条件的情况的时候脑子要转个弯。
判断的部分我写成了一个函数,就是判断牛之间最小距离大于m的函数,函数的判断方法就是记录之间间隔大于等于m的房子的个数,如果这个记录的个数大于总共牛的个数,那么肯定有方案把牛都放进去,而且两两距离不小于m。
判断好了返回个true就好了。
然后在二分的过程中有一些小讲究,left、right还有mid的取值变化要根据我们要找的东西来设,我们要找的东西,其实是满足条件最大的m。
带清晰注释的题解
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
int a[100],n,c;
bool fun(int m){//只要相隔m的牛的个数多余实际牛的个数,就可以返回true
int cnt = 1,cur = 0,next=1;//cur是当前牛编号,next是下一只牛的编号,cnt是用来计数的
while(next<n){
next++;//指向下一只牛
if(a[next]-a[cur]>=m){//当前编号牛的位置与下一编号牛的位置只要大于m
cnt++;//满足条件的牛的个数加1
cur=next;//把当前牛调整为next
}
}
if(cnt>=c)return true;//只要相隔m的牛的个数多余实际牛的个数,就可以返回true
else return false;
}
int main ()
{
printf("please input the number of room:");
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
printf("input the number of cow: ");
scanf("%d",&c);
int left=1,right=(a[n-1]-a[0])/(c-1);
//求解下界是1,就是他们紧挨着的情况,
//上界是最大值-最小值除(牛的个数-1),因为两头都可以取值,蓝哥思考一下为什么是牛的个数-1
while(left<right){
int mid = ((left+right)+1)/2;
//精髓,此处是为了确保二分法能取到最右边的数,故要让除二之前先加一,即向上取整
if(fun(mid))left=mid;
//此处我们需要找到满足条件的最大的值,所以如果mid点满足条件,要让left=mid,继续找更大的点
else right=mid-1;
}
cout<<"the answer is : "<<left<<endl;
//最后一次求得的满足条件的值mid,已经赋给了left,做一输出left
return 0;
}
希望能帮助到你
//来自@小钟