POJ - 2456 二分+贪心


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;
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值