POJ 2456 (二分)

题目链接http://poj.org/problem?id=2456

题目大意:n个房子,m头牛,房子有一个横坐标,问将m头牛塞进房子,每两头牛之间的最大间隔是多少。

解题思路

不难看出应该二分房子间隔,找一个最大的可行间隔。

首先将房子坐标排序,这样只需从第1个房子开始塞牛就行了,且第一个房子肯定得塞一只牛,才能保证空间的有效利用。

这样,每次对于一个间隔,从第一个房子开始塞牛:

①如果上一个房子坐标last+间隔<=h[i],那么这个房子肯定得塞牛,才能有效利用空间,更新last,cnt++。

②否则不能塞牛,去下一个房子。

这样,只要最后cnt>=m,这个间隔就是可行的。

 

关键在于确定二分的边界,左边界l可以确定是排序之后相邻两个房子的差的最小值。这也是可以尝试的最小间隔。

我一开SB地认为右边界就是两个相邻两个房子差的最大值。其实不对,因为牛之间可以隔好多房子。其实r=h[n]-h[1]/(m-1)

如果你比较机智而且又懒,其实l=0,r=h[i]就行了,反正范围大点也不会超时orz。

以后确定范围直接脑残0~最大好了。

 

#include "cstdio"

#include "algorithm"

using namespace std;

int h[100005],n,m,ans;

bool check(int dist)

{

    int cnt=1,last=h[1];

    for(int i=2;i<=n;i++) if(last+dist<=h[i]) {last=h[i];cnt++;}

    if(cnt>=m) return true;

    else return false;

}

int main()

{

    //freopen("in.txt","r",stdin);

    int l=0x3f3f3f3f,r=-1;

    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;i++) scanf("%d",&h[i]);

    sort(h+1,h+n+1);

    for(int i=2;i<=n;i++) l=min(l,h[i]-h[i-1]);

    r=(h[n]-h[1])/(m-1);

    while(l<=r)

    {

        int mid=l+(r-l)/2;

        if(check(mid)) {ans=mid;l=mid+1;}

        else r=mid-1;

    }

    printf("%d\n",ans);

}

 

13591899 neopenx 2456 Accepted 548K 110MS C++ 661B 2014-11-02 19:22:27

你可能感兴趣的:(poj)