1.题目
好斗的奶牛
描述
农民约翰建造了一个新的长谷仓,有 N (2 <= N <= 100,000) 个畜栏。摊位位于位置 x1,...,xN (0 <= 习 <= 1,000,000,000) 处的一条直线。
他的 C (2 <= C <= N) 奶牛不喜欢这种牛舍布局,一旦被放入畜栏,它们就会变得相互攻击。为了防止奶牛互相伤害,FJ希望将奶牛分配到畜栏,以便它们中的任何两个之间的最小距离尽可能大。最大最小距离是多少?
输入
* 第 1 行:两个空格分隔的整数:N 和 C
* 第 2..N+1 行:第 i+1 行包含整数停档位置,习
输出
* 第 1 行:一个整数:最大最小距离
样例输入
5 3 1 2 8 4 9
样例输出
3
2.分析
所有的畜栏都在一条直线上,畜栏坐标的范围是【0,1000000000】,那么奶牛所放置的畜栏的最大间隔距离就是畜栏的坐标范围,通过二分法来不断限定畜栏的坐标范围,比如第一次[0,500000000],[500000001,1000000000]在这两个范围中选择,用check()函数来判断,奶牛最大间隔距离m=500000000,如果这个距离可以放下所有的奶牛,那么就可以在较大范围[500000001,1000000000]范围内进行搜索,下界A=m+1,否则要在较小范围[0,500000000]范围内搜索,上界B=m-1。至于为什么i的最大值选取35,是log2(1000000001)≈30.9,所以进行35次迭代一定能确定ans的值。
3.代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100005;
int N,C;
int x[maxn];
bool check(int m)
{
int cnt=1,k=1;
for(int i=2;i<=N;i++)
{
if(x[i]-x[k]>=m)
{
cnt++;
k=i;
}
}
if(cnt>=C) return 1;
else return 0;
}
int main()
{
scanf("%d%d",&N,&C);
for(int i=1;i<=N;i++)
{
scanf("%d",&x[i]);
}
sort(x+1,x+1+N);
int A=0,B=1000000000,ans=0;
for(int i=0;i<35;i++)
{
int m=(A+B)/2;
if(check(m)) ans=m,A=m+1;
else B=m-1;
}
printf("%d\n",ans);
return 0;
}