题目信息:
疯牛
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1,000,000,000).
但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢?-
输入
-
有多组测试数据,以EOF结束。
第一行:空格分隔的两个整数N和C
第二行——第N+1行:分别指出了xi的位置
输出
- 每组测试数据输出一个整数,满足题意的最大的最小值,注意换行。 样例输入
-
5 3 1 2 8 4 9
样例输出
-
3
-
有多组测试数据,以EOF结束。
qsort函数排序,然后最小距离为1,最大距离为最后一个隔间的坐标值减去第一个隔间的坐标值,利用二分查找,判断两隔间举例满足大于中间值的总数是否大于牛的总数,查到区间大小为1,区间左端已判断的值即为最小距离。特别注意的是当牛数量C为2时,最小距离极为最后一个隔间的坐标值减去第一个隔间的坐标值。
代码部分:
#include <stdio.h>
#include <stdlib.h>
int a[100001];
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int main()
{
int n,c,i,head,tail,arrow,num,j,k;
while(scanf("%d%d",&n,&c)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
qsort(a,n,sizeof(a[0]),cmp);
if(c==2)
printf("%d\n",a[n-1]-a[0]);
else
{
head=1;
tail=a[n-1]-a[0];
while(tail-head>1)
{
arrow=(head+tail)/2;
j=0;
k=1;
num=0;
for(i=1;i<n;i++)
{
if(a[k]-a[j]>=arrow)
{
num++;
j=k;
k++;
}
else
k++;
}
if(num>=c-1)
head=arrow;
else
tail=arrow;
}
printf("%d\n",head);
}
}
return 0;
代码优化:
#include <stdio.h>
#include <stdlib.h>
#define Max_size 100020
int x[Max_size];
int N,C;
int com(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
bool Judge(int v)
{
//v表示两牛之间最小的距离值
int i;
int num=0;//房子编号
int t;
for(i=1;i<C;i++)//对牛计数
{
t=num+1;
while(t<N&&x[t]-x[num]<v)//t跳出时 t==N说明列举了 num之后的所有房子都无法满足两房子之间距离<=v值
t++;//反之,则说明找到了满足条件的房子
if(t==N)
return false;
num=t;
}
return true;
}
int main()
{
int i;
int bottom,top;
int mid;
while(~scanf("%d%d",&N,&C))
{
for(i=0;i<N;i++)
scanf("%d",x+i);
qsort(x,N,sizeof(x[0]),com);//因为每个房间的坐标是混乱的,所以对每个房间的坐标进行小到大排序
bottom=0;top=(x[N-1]-x[0])*2;//确定上界和下界
while(top-bottom>1)
{
mid=(top+bottom)/2;
if(Judge(mid))
bottom=mid;//mid值能满足条件 说明答案的区间为[mid,top)
else top=mid;//mid 值不能满足条件 说明答案的区间为(bottom,mid)
}
printf("%d\n",bottom);
}
return 0;
}