Aggressive cows 二分法求解

本文通过一个具体的农场牛棚布局问题,介绍了如何使用二分法求解最大化的最小距离。通过逐步分析代码和算法思路,解释了如何确定搜索范围、设计判断函数以及实现二分查找的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    算法训练至二分专题,基础的二分思想虽然了解,但做题还是很懵。看来还是思想理解不够透彻,题目刷得不够多。

    见题目:

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头牛放到n间牛棚中,牛很狂暴,农夫的目的是让相邻牛之间的距离尽可能远,每种安放方案都有一个相邻牛棚之间的最小值,求这种最小值的最大化是多少?

    首先给出代码,结合代码进行分析:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,c,a[100005];
int judge(int x)
{
	int i,s=1,p=a[0];
	for(i=1; i<n; i++)
	{
		if(a[i]-p>=x)
		{
			s++;
			p=a[i];
		}
	}
	return s;
}
int main()
{
	int i,j;
	scanf("%d%d",&n,&c);
	for(i=0; i<n; i++)
		scanf("%d",&a[i]);
	sort(a,a+n);
	int l=0,r=a[n-1]-a[0];
	while(r>=l)
	{
		int mid=(l+r)>>1;
		if(judge(mid)>=c)
			l=mid+1;
		else
			r=mid-1;
	}
	printf("%d\n",l-1);
	return 0;
}

    题目分析:二分求解。网上很多大神都是直接给出二分求解的思路,但我们这种入门级菜鸟在理解代码上有点困难,遂彻底理一下思路,在这里记录一下。首先将牛棚的位置排序,因为所求的解为相邻牛棚间的最小值,所以所求结果肯定在0到最后一个牛棚和第一个牛棚之间的距离差的范围内,即(0,a[n-1]-a[0])。对此区间进行二分求解,在套用二分求解的模板上,需要定义一个判断函数来判断当前的值是否可行,此时定义judge函数。

int judge(int x)
{
	int i,s=1,p=a[0];
	for(i=1; i<n; i++)
	{
		if(a[i]-p>=x)
		{
			s++;
			p=a[i];
		}
	}
	return s;
}

    定义s指的是在最小值在x的情况下,对牛棚数组进行遍历,判断最终满足该最小值条件的情况下能放入多少头牛,若能放入的牛的数目是大于等于要求的c头牛的话,则满足条件,且最小值还可以继续扩大,若不满足的话则说明最小值取大了,对左侧区间再进行二分查找。

    那么怎样通过数组遍历来判断呢,首先需要理解的一点是。a[0]是必须放入符合条件的情形中的,假设a、b、c三点即为最终所求牛棚的位置,则这种情形下最小值即为min(b-a,c-b),a是非起点的,那么a>a[0],那么此时用a[0]代替a则最小值为min(b-a[0],c-b)肯定是大于第一个结果的,所以起始点肯定需要添加。此时定义s=1,s是指能满足条件的牛棚的数目,对牛棚数组进行遍历,若遇到第一牛棚它的位置减去起始点位置大于等于x则将此点加入,并以此点为起点寻找它的下家,此时s++。最终遍历完数组即可求出在这种最小值的情形下可以满足条件的牛棚数若大于等于题目要求的牛数则满足要求。最终二分至结果。题目理解大抵如此,若有错误欢迎批评指正。

    题目刷得还是太少,水平还是太菜,唯有努力努力再努力。

    特记下,以备后日回顾。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值