#2020.01.14训练题解#二分入门(F题)

本文解析了POJ-2456 Aggressive Cows问题,通过二分搜索算法寻找牛棚间最大最小距离,确保任意两头牛之间的距离最大化。介绍了算法思路、关键步骤及AC代码实现。

题源POJ-2456

POJ-2456-Aggressive cows

Description
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?

Input
Line 1: Two space-separated integers: N and C
Lines 2…N+1: Line i+1 contains an integer stall location, xi

Output
Line 1: One integer: the largest minimum distance

Sample Input
5 3
1
2
8
4
9

Sample Output
3

Hint
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.

题意

  • 输入N和C,代表有N个牛棚和C头牛
  • 下面输入N个牛棚的x坐标位置
  • 输出把这C头牛一头安置在一个牛棚后,两两之间的最小距离,最大是多少

题解

  • 二分的对象是最后要求的最小距离,二分得到其最大值
  • 要安置牛,那么牛棚的坐标得进行sort排序
  • 对于每一次二分出的mid,用check函数判断是否满足安置C头牛
  • 注意C头牛,只要有C-1个间距满足即可,循环的最大次数C-1
  • 每次用now和before记录坐标,分别是现在准备尝试安置牛的坐标,以及上一次安置好牛的坐标
  • while循环还没到最后一个牛棚且不满足二分出的距离的情况,now往后推移
  • 如果还没循环完C-1次now就到了最后一个牛棚下标之后,即nreturn 0;意味着此mid不成立
  • 如果循环完C-1次,就能安置C头牛,则**return 1;**啦٩(๑>◡<๑)۶
  • 出现right==left+1要么是mid满足left=mid;要么是mid不满足后,right=mid;
  • 所以输出left则是mid满足后的mid值,或mid不满足后,满足题意的left(right不满足)

涉及知识点

  • 二分 算法(此题属于整数二分)
  • 对于二分的算法-详见链接博客介绍二分

AC代码

#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;
int n,c,pos[100010];//n有几个牛棚,c有几头牛,pos是牛棚的位置 
int check(int distance)
{
    int before=0;
    for(int i=1;i<c;i++)//c头牛,两两之间才有距离,所以只要测c-1次距离就行啦
    {
        int now=before+1;
        while(now<n&&pos[now]-pos[before]<distance)
		{//要求要大于distance,<就只能再试试下一个,如果试着试着到底了,这个distance就错了 
			now++;
		}
        if(now==n) return 0;//找到最后一个牛棚了 
        before=now;//如果没到底找到了满足>=distance的位置now,那就传给before进行下一次 
    }
    return 1;//当顺利做完c-1遍的时候,说明distance可行 
}
int main()
{
    while(~scanf("%d %d",&n,&c))
    {
        for(int i=0;i<n;i++)
        {
        	scanf("%d",&pos[i]);
		}
        sort(pos,pos+n);//pos数组升序 
        int left=0,right=1000000001;
        while(right>left+1)//不可相邻不然出现除以二就是非整数 
        {
            int mid=(left+right)/2;
            if(check(mid)) left=mid;//放得下就可能是最小距离还不够大,试试更大的 
            else right=mid;//放不下的话就是最小距离太大了,要缩小 
        }
        printf("%d\n",left);
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值