疯牛

疯牛

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述

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

有多组测试数据,以EOF结束。
第一行:空格分隔的两个整数N和C
第二行——第N+1行:分别指出了xi的位置
输出

每组测试数据输出一个整数,满足题意的最大的最小值,注意换行。
样例输入

5 3
1
2
8
4
9
样例输出

3




这道题就是在说
农民希望每个牛之间的距离尽可能的大,有很多种方案,每个方案都有一个最小距离,我们就是要求出这个最小距离的最大值
我们可以知道,首先第一头牛肯定是要放在第一个牛棚里的

假设每个方案的最小距离是min,牛棚之间的距离为d。
也就是说di+1-di>=min,就是相邻牛棚之间的距离是大于min的
所以我们可以这样,首先先对牛棚进行排序。接着min的范围是从0到bar[N-1]-bar[0]的,即是从0到最远距离,
所以我们可以从0到bar[N-1]-bar[0]中遍历,取每个min,看这个用这个距离min能否放下所有的牛

即看每个牛棚之间的距离是否能满足bar[i]-now>=min。
首先第一头牛放在第一个牛棚,接着遍历每个牛棚,看第i个牛棚bar[i]-bar[0]是否大于等于min,如果可以就放下了一头,接着继续判断下一个牛棚跟第二个牛棚之间的距离是否大于等于min,直到所有的牛都被放下。如果可以的话就说明这个min可以作为一种方案的最小距离,然后找出最大的min。这个方法就是check方法

但是数据量有点大,单纯的从0一直遍历到bar[N-1]-bar[0]有点太慢了,所以采用了二分查找,二分查找的判断条件就是check方法
如果check可以的话,说明当前的这个min是可以放下C头牛的,我们就放大这个min看能否接着放下C头牛
如果check不行的话,说明这个min放不下C头牛,我们就要缩小这个min使得他能放下C头牛
总之思路就是这样,用二分其实也是等同于顺序,只是要更快,并不是什么高深的东西
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<string>
#include<stdio.h>
#include<memory.h>
#include<string.h>
using namespace std;
int bar[100005];
int N, C;
bool check(int min) {
    //每个牛棚之间的距离都要大于v 看是否能放下所有的牛
    int cnt = 1, i;        //第一头牛放在第一个牛棚
    int now=bar[0];    //当前放下的牛棚 即第一头放在了第一个牛棚
    for (i = 1; i < N; i++) {
        if (bar[i] - now >= min) {
            cnt++;
            now = bar[i];
            if (cnt >= C) return true;    //可以放下所有的牛
        }
    }
    return false;
}
int main()
{
    int i, j;
    while ((scanf("%d %d", &N, &C)) != EOF) {
        for (i = 0; i < N; i++) {
            scanf("%d", &bar[i]);
        }
        sort(bar, bar + N);

        //目的是让每个牛棚之间的距离尽可能大 接着是求出这些方案中的最小距离的最大值
        //假设当前的最小值为x,如果判断出最小差值为x时可以放下C头牛,就先让x变大再判断;
        //如果放不下,说明当前的x太大了,就先让x变小然后再进行判断。
        //直到求出一个最大的x就是最终的答案
        int low = 0, high = bar[N - 1] - bar[0];    //high为最长距离。要从 0~最长距离 用二分法中找出一个最大距离距离能放下N头牛
        int mid;
        while (high >= low) {
            mid = (low + high) / 2;
            if (check(mid)) low = mid + 1;    //判断这个min是否可以放下C头牛 可以的话就放大
            else high = mid - 1;    //不可以的话只能缩小了
        }
        cout << high << endl;
    }
    return 0;
}       





















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值