POJ2456—Aggressive cows—二分法求 the largest minimum

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
 
  
 
  
 
 

题目大意::给出N个数(假设为数列a),从中选出C个(假设有k种),每一种中C个数的差有一个最小值min。从k中情况中选出min最大的一一种情况。

解题思路::我们可以换一种思路来看这道题,C个数差的最小值必然是排序后相邻的两个数相减得来,所以先对N个数进行排序。要求最大的最小值,必然要尽可能的增大数与数之间的差距,也就是我们要剔除数列 a 中的元素只剩下C个。我们假设
the largest minimum 是mid = 2,排序后a[]={1,2,3,5,6}那么a[1] - a[0] = 1 < 2,所以把a[1]剔除,然后a[2] - a[0] =2==2,a[2]保留,然后求a[3] - a[2] = 2==2,a[2]保留,依次类推,通过改变mid的值使的数列中只剩C个数。我们可以做一个C-1次的循环,如果在循环中用到了a最后一个元素,依旧没有满足循环,mid就太大,反之就太小。当然我们也可以对元素个数进行记录,此处不做介绍。
下面就是如何改变mid的值。我们通过二分法,定义l(left),r(right),使mid = (l+r)/2;通过进行比较,更新l,或者r。更新原则是::if(用到a[]最后一个数){r = mid;} else {l = mid;} 在(r>l+1)的情况下一直循环。

解题代码::

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
/**********************
*******头文件**********
**********************/
const int N = 1e5 + 5;
int n,c;
int a[N];
bool ok(int mid) {
    int last = 0;
    for (int i = 1; i < c; ++i) {//循环c-1次
        int cur = last + 1;
        while (a[cur] - a[last] < mid && cur < n) cur ++;//在这里cur会逐渐累加
        if (cur == n) return false;//出现a中最后一个元素后依旧不能满足循环
        last = cur;
    }
    return true;//没有出现过最后一个元素
}

int main() {
    while (scanf("%d%d", &n, &c)!=EOF) {
        for (int i = 0; i < n; ++i) scanf("%d", a + i);
        sort(a, a + n);//排序一定不能忘
        int l = 0, r = INF;//这里的r不一定要是INF,但是要大于排序后的a[n-1] - a[0]
        while (r > l+1) {
            int mid = (l + r) / 2;
            if (ok(mid)) l = mid;//没有出现最后一个数
            else r = mid;
        }
        printf("%d\n", l);//输出l,标书the largest mimmum
    }
    return 0;
}
题目不难,为了学习二分法。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值