POJ - 2456的题目链接
(一)题意
emm…开始读了有点没读懂,实际上大概就是告诉你,给你N个牛棚,每一个牛棚都有它的编号,再给你C头牛,你现在就要把这C头牛全部丢到牛棚里面,求出最小的两头有牛的牛棚编号差值中的最大的那个。。。这个有点绕,大概就是,把C头牛丢到N个牛棚里面,有很多种丢法,但每次,两两有牛的牛棚编号之间的差值肯定会有一个最小值,我们要求的是这么多种丢法中的最小值集合中的最大的那个。
(二)思路
参考了这位大佬的思路和代码
大佬分析的非常不错,博主再分析一波。简单来讲,我们现在有N个牛棚,但可惜的是。这N个牛棚编号是无序的。SO,我们可以先准备一个数组储存着所有的牛棚编号,再调用头文件<algorithm>
中的sort函数(非常nice的一个库函数,就不用写快排了,默认是从小到大排序)。将这N个牛棚编号按从小到大的顺序排列好,这样,两个牛棚编号差值的最大值,最大不过数组两个端点的差值了。(因为已经从小到大排序好了),最小呢,即是0(牛棚编号可能相同)。然后,我们需要运用二分的方法,(因为N太大的话,暴力是肯定会WA的)。找到每此临时区间中的中点(通过二分枚举最小值来求。假设当前的最小值为x,如果判断出最小差值为x时可以放下C头牛,就先让x变大再判断;如果放不下,说明当前的x太大了,就先让x变小然后再进行判断。直到求出一个最大的x就是最终的答案),再结合判断函数 找个那个最大的,符合条件的(能把所有的牛都能放完)牛棚编号差值,即为结果。
(三)代码
#include <algorithm>
#include <queue>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <string>
#include <iostream>
using namespace std;
const int N = 100005;
int a[N], n, c;
bool panduan(int x) //判断此时的X能否能将C头牛全部放完
{
int cot=1,tmp=a[0]; //将第一头牛扔到a[0]位置;
for(int i=1;i<n;i++)
{
if(a[i]-tmp>=x) //如果满足此条件,那就把牛扔到tem位置上。
{
cot++;
tmp=a[i];
if(cot>=c) return true; //能把C头牛放完
}
}
return false;
}
int erfen() //找到最大的最小距离
{
int l=0,r=a[n-1]-a[0];
//初始时, l为0(牛棚编号差值最小),r为a[n-1]-a[0](牛棚编号差值最大)
while(l<=r)
{
int mid= (l+r)/2;
if(panduan(mid)) l=mid+1;
//如果 mid能把C头牛全放进N,那就让l=mid+1,直到找到最大的mid
else r=mid-1;
//如果 mid放不了C头牛,只能将r=mid-1,直到让mid能放C头牛
}
return l-1; //根据之前的if条件。此时l-1才等于最大的mid
}
int main()
{
while(scanf("%d%d",&n,&c)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
sort(a,a+n); //快排
printf("%d\n",erfen());
}
return 0;
}