POJ-2456-Aggressive cows
Description
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?
Input
Line 1: Two space-separated integers: N and C
Lines 2…N+1: Line i+1 contains an integer stall location, xi
Output
Line 1: One integer: the largest minimum distance
Sample Input
5 3
1
2
8
4
9
Sample Output
3
Hint
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.
题意
- 输入N和C,代表有N个牛棚和C头牛
- 下面输入N个牛棚的x坐标位置
- 输出把这C头牛一头安置在一个牛棚后,两两之间的最小距离,最大是多少
题解
- 二分的对象是最后要求的最小距离,二分得到其最大值
- 要安置牛,那么牛棚的坐标得进行sort排序
- 对于每一次二分出的mid,用check函数判断是否满足安置C头牛
- 注意C头牛,只要有C-1个间距满足即可,循环的最大次数是C-1次
- 每次用now和before记录坐标,分别是现在准备尝试安置牛的坐标,以及上一次安置好牛的坐标
- while循环还没到最后一个牛棚且不满足二分出的距离的情况,now往后推移
- 如果还没循环完C-1次,now就到了最后一个牛棚的下标之后,即n,return 0;意味着此mid不成立
- 如果循环完C-1次,就能安置C头牛,则**return 1;**啦٩(๑>◡<๑)۶
- 要出现right==left+1要么是mid满足后left=mid;要么是mid不满足后,right=mid;
- 所以输出left则是mid满足后的mid值,或mid不满足后,满足题意的left(right不满足)
涉及知识点
- 二分 算法(此题属于整数二分)
- 对于二分的算法-详见链接博客介绍二分
AC代码
#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;
int n,c,pos[100010];//n有几个牛棚,c有几头牛,pos是牛棚的位置
int check(int distance)
{
int before=0;
for(int i=1;i<c;i++)//c头牛,两两之间才有距离,所以只要测c-1次距离就行啦
{
int now=before+1;
while(now<n&&pos[now]-pos[before]<distance)
{//要求要大于distance,<就只能再试试下一个,如果试着试着到底了,这个distance就错了
now++;
}
if(now==n) return 0;//找到最后一个牛棚了
before=now;//如果没到底找到了满足>=distance的位置now,那就传给before进行下一次
}
return 1;//当顺利做完c-1遍的时候,说明distance可行
}
int main()
{
while(~scanf("%d %d",&n,&c))
{
for(int i=0;i<n;i++)
{
scanf("%d",&pos[i]);
}
sort(pos,pos+n);//pos数组升序
int left=0,right=1000000001;
while(right>left+1)//不可相邻不然出现除以二就是非整数
{
int mid=(left+right)/2;
if(check(mid)) left=mid;//放得下就可能是最小距离还不够大,试试更大的
else right=mid;//放不下的话就是最小距离太大了,要缩小
}
printf("%d\n",left);
}
return 0;
}