算法训练至二分专题,基础的二分思想虽然了解,但做题还是很懵。看来还是思想理解不够透彻,题目刷得不够多。
见题目:
Description
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
* Lines 2..N+1: Line i+1 contains an integer stall location, xi
Output
Sample Input
5 3 1 2 8 4 9
Sample Output
3
Hint
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.
首先给出代码,结合代码进行分析:
#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++。最终遍历完数组即可求出在这种最小值的情形下可以满足条件的牛棚数若大于等于题目要求的牛数则满足要求。最终二分至结果。题目理解大抵如此,若有错误欢迎批评指正。
题目刷得还是太少,水平还是太菜,唯有努力努力再努力。
特记下,以备后日回顾。