一本通网站 1433:例题1愤怒的牛

Posted xcg123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一本通网站 1433:例题1愤怒的牛相关的知识,希望对你有一定的参考价值。

原题 传送门

【题目描述】

农夫 John 建造了一座很长的畜栏,它包括N (2 ≤ N ≤ 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 ≤ xi ≤ 1,000,000,000). 但是,John的C (2 ≤ C ≤ N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢

【输入】

第一行:空格分隔的两个整数N和C;

第二行---第N+1行:i+1行指出了xi的位置。

【输出】

一个整数,最大的最小值。

【输入样例】

5 3
1 2 8 4 9

【输出样例】

3

【提示】

把牛放在1,4,8这样最小距离是3。

类似的最大值最小化或者最小化最大值的问题,通常用二分法就可以很好的解决。我们定义:

设C(d)表示可以安排牛的位置,并使得最近的两头牛的距离不小于d。

那么问题就转化为求满足C(d)的最大的d,另外,最近的间距不小于d也可以看成是所以牛的间距不小于d,因此就可以用C(d)表示可以安排牛的位置,并使得任意两头牛的距离不小于d。对于这个问题的判断,使用贪心法便可非常 容易地求解。

1.对牛舍的位置x进行排序;

2.把第一头牛放入x0的牛舍;

3.如果第i头牛放入了xj间牛舍,则第i+1头牛就要放入满足xj+d<=xk的最小的牛舍xk中。

对x的排序只需在最开始是进行一次就可以了,每一次判断对每头牛最多进行一次处理,因此算法的时间复杂度是O(nlogn)。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int read()

    char ch=getchar();
    int a=0,x=1;
    while(ch<0||ch>9)
    
        if(ch==-) x=-x;
        ch=getchar();
    
    while(ch>=0&&ch<=9)
    
        a=(a<<3)+(a<<1)+(ch-0);
        ch=getchar();
    
    return a*x;

int n,m,x[100005];
bool check(int d)

    int cow=1;                 //第一个牛舍放牛 
    int dis=x[1]+d;            //后面的牛舍要满足大于等于dis才可以放牛 
    for(int i=2;i<=n;i++)
    
        if(x[i]>=dis)
        
            cow++;              //放进一头牛 
            dis=x[i]+d;         //找下一个牛舍应符合的条件 
        
    
    return cow>=m;              //判断是否够m个 

int main()

    n=read();
    m=read();
    for(int i=1;i<=n;i++) x[i]=read();
    sort(x+1,x+1+n);           //按照牛舍的位置从小到大排序 
    int l=0,r=x[n]-x[1];
    while(l<=r)                //二分找答案 
    
        int mid=(l+r)/2;
        if(check(mid)) l=mid+1;//若check为true说明找的这个d偏小,我们要往右区间找 
        else r=mid-1;          //否则则偏大,我们往左区间找 
    
    cout<<r;                   //当前r就是最大的d 
    return 0;

 

以上是关于一本通网站 1433:例题1愤怒的牛的主要内容,如果未能解决你的问题,请参考以下文章

『一本通』二分与三分

一本通网站 1424:例题3喷水装置 及 贪心总结

信息学奥赛一本通Part1.2 基础算法-二分与三分

一本通tarjan题目

信息学竞赛一本通提高版AC题解—例题1.1活动安排

一本通搜索与回溯例题5.2