Aggressive cows 清晰题解 (poj 2456)(USACO 2005 February Gold)

问题描述


Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
输入
* Line 1: Two space-separated integers: N and C

* Lines 2..N+1: Line i+1 contains an integer stall location, xi
输出
* Line 1: One integer: the largest minimum distance
样例输入
5 3
1
2
8
4
9
样例输出
3
提示
OUTPUT DETAILS:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.

Huge input data,scanf is recommended.
 


个人理解

这个题我已开始看的也云里雾里,它的英文表达太绕了,后来理解一下其实意思就是,按顺序告诉你各个房子的位置,让你尽量分散地把牛放到房子里面去,然后求出尽量分散地情况下,最近的两头牛的距离。


解法

这个题解法不唯一,其实就是一个非常典型的二分查找题,只不过你判断满足条件的情况的时候脑子要转个弯。

判断的部分我写成了一个函数,就是判断牛之间最小距离大于m的函数,函数的判断方法就是记录之间间隔大于等于m的房子的个数,如果这个记录的个数大于总共牛的个数,那么肯定有方案把牛都放进去,而且两两距离不小于m。

判断好了返回个true就好了。

然后在二分的过程中有一些小讲究,left、right还有mid的取值变化要根据我们要找的东西来设,我们要找的东西,其实是满足条件最大的m。


带清晰注释的题解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;

int a[100],n,c;

bool fun(int m){//只要相隔m的牛的个数多余实际牛的个数,就可以返回true
    int cnt = 1,cur = 0,next=1;//cur是当前牛编号,next是下一只牛的编号,cnt是用来计数的
    while(next<n){
        next++;//指向下一只牛
        if(a[next]-a[cur]>=m){//当前编号牛的位置与下一编号牛的位置只要大于m
            cnt++;//满足条件的牛的个数加1
            cur=next;//把当前牛调整为next
        }
    }
    if(cnt>=c)return true;//只要相隔m的牛的个数多余实际牛的个数,就可以返回true
    else return false;
}

int main ()
{
    printf("please input the number of room:");
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    printf("input the number of cow: ");
    scanf("%d",&c);
    int left=1,right=(a[n-1]-a[0])/(c-1);
    //求解下界是1,就是他们紧挨着的情况,
    //上界是最大值-最小值除(牛的个数-1),因为两头都可以取值,蓝哥思考一下为什么是牛的个数-1
    
    while(left<right){
        int mid = ((left+right)+1)/2;
        //精髓,此处是为了确保二分法能取到最右边的数,故要让除二之前先加一,即向上取整
        
        if(fun(mid))left=mid;
        //此处我们需要找到满足条件的最大的值,所以如果mid点满足条件,要让left=mid,继续找更大的点
        
        else right=mid-1;
    }
    cout<<"the answer is : "<<left<<endl;
    //最后一次求得的满足条件的值mid,已经赋给了left,做一输出left
    return 0;
}

希望能帮助到你

//来自@小钟

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值