POJ:2456 Aggressive cows(z最大化最小值)

描述

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

 
输入
第一行:空格分隔的两个整数N和C
第二行——第N+1行:分别指出了xi的位置
输出
每组测试数据输出一个整数,满足题意的最大的最小值,注意换行。
样例输入
5 3
1
2
8
4
9
样例输出
3

意要表达的是:把C头牛放到N个带有编号的隔间里,使得任意两头牛所在的隔间编号的最小差值最大。

分析:这是一个最小值最大化的问题。先对隔间编号从小到大排序,则最大距离不会超过两端的两头牛之间的差值,最小值为0。所以我们可以通过二分枚举最小值来求。假设当前的最小值为x,如果判断出最小差值为x时可以放下C头牛,说明当前的x有点小,就先让x变大再判断;如果放不下,说明当前的x太大了,就先让x变小然后再进行判断。直到求出一个最大的x就是最终的答案。

现在来搞下解题步骤:

C(d)=可以安排牛的位置使得最近的两头牛的距离都不小于d

那么现在问题就变成求满足C(d) 的最大d,另外最近的间距不小于d也可以说成是所有牛的间距不小于d;

在问题上的判断使用贪心法便可以非常容易地求解。

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

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

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

AC 代码:

#include<stdio.h>
#include<algorithm>
#define MAX 101000
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int a[MAX];
bool C(int d)
{
    int last=0;
    for(int i = 1 ; i < m ; i++)
    {
        int crt=last+1;
        while(crt<n&&a[crt]-a[last]<d)///只需要比较k-1次找出最适合的值d来搞k头牛,用last&crt来表示上一头牛和当前牛的位置
            crt++;
        if(crt==n)
            return false;///到达最大值n。说明d的值小了
        last = crt;
    }
    return true;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < n ; i++)
        scanf("%d",&a[i]);
    sort(a,a+n);
    int st = 0,en=INF,mid;
    while(en-st>1)
    {
         mid=(en+st)/2;
        if(C(mid)==false)
            en=mid;
        else
            st=mid;
    }
    printf("%d\n",(en+st)/2);///个人突杨想到的问题,因为我不知道是en还是st
}
View Code

另一种解法:

#include<stdio.h>
#include<algorithm>
#define MAX 101000
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int a[MAX];
bool C(int d)
{
    int sum=0;
    int ans=1;
    for(int i=1;i<n;i++)
    {
        if((sum+a[i]-a[i-1])<d)
        {
            sum+=a[i]-a[i-1];

        }
        else
        {
            sum=0;
            ans++;
        }
    }
    if(ans>=m)
        return true;
    return false;
}
int main()
{
    int en=-1,st=INF;
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < n ; i++)
    {
        scanf("%d",&a[i]);
    }

    sort(a,a+n);
    en=a[n-1]-a[0];
    for(int i=1;i<n;i++)
    {
        st=min(st,a[i]-a[i-1]);

    }
     while(en-st>1)
     {
         int mid=(en+st)/2;
          if(C(mid))
            st=mid;
          else
            en=mid;
     }
    printf("%d\n",(st+en)/2);///个人突杨想到的问题,因为我不知道是en还是st
}
View Code

 

posted @ 2018-04-23 20:46  shuai_hui  阅读(175)  评论(0编辑  收藏  举报