POJ 2456 Aggressive cows 二分搜索

Aggressive cows
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 6727 Accepted: 3360

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个点,然后在这C个点里面相邻的两个点的距离中的最小距离为min的话,求最大的min。即最小值最大化。

思路:二分搜索。
首先想说的是二分不光是查找值,还可以搜索,即先确定一个解,再判断是否可行,然后根据判断是否成立来缩小搜索区间,最后确定一个正确解。
我们平时用的二分查找就是下面这样的:
while(l<r)
{
	m=(l+r)/2;
	if(C(m))
		l=m+1;
	else
		r=m;
}
我们只要把l和r改一下,保证正确解在[l,r]中,我们就能用二分搜索,重点就是C(m)的判断,这里是解题的重点。
C()函数的参数就是一个解,然后去判断这个参数m是否满足要求。本题中:设参数为k,说明要验证最小距离为k是否能行,那么如果最小距离为k,说明对于这N个点中的每一个点a,如果a点被选中了,其前后距离小于k的范围内的点不能再被选了,即在(a-k,a+k)的点不能被选中,这样的话计算一共能选出来的点的个数是否多于或等于C个,如果多于或等于说明最小距离为k时可以,否则不行。  由此可得C( )函数:
int C(ll k)
{
	ll i,sum=0,t;
	for(i=0;i<n;i++)
	{
		t=a[i];
		while(i<n && a[i]-t<k)
			i++;
		sum++;
		i--;
	}
	return sum>=c;
}

本题ac代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
typedef __int64 ll;
#define INF 1e10

ll a[1000005];
int n,c;

int C(ll k)
{
	ll i,sum=0,t;
	for(i=0;i<n;i++)
	{
		t=a[i];
		while(i<n && a[i]-t<k)
			i++;
		sum++;
		i--;
	}
	return sum>=c;
}

int main()
{
	int i,j;
	ll l=0,r=INF,m;
	scanf("%d%d",&n,&c);
	for(i=0;i<n;i++)
		scanf("%I64d",&a[i]);
	sort(a,a+n);
	while(l<r)
	{
		m=(l+r)/2;
	//	printf("r=%I64d\n",m);
	//	printf("l=%I64d r=%I64d\n",l,r);
		if(C(m))
			l=m+1;
		else
			r=m;
	}
	printf("%I64d\n",r-1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值