CSU-ACM2017暑假集训2-二分搜索 E - Aggressive cows

本文介绍了一种解决农民John分配牛棚问题的算法。该问题要求在一系列位置已知的牛棚中分配一定数量的奶牛,使得任意两头奶牛间的最小距离尽可能大。文章通过使用二分查找与贪心策略结合的方法来高效地寻找最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E - Aggressive cows

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. 

二分枚举答案。
在vector中按答案找两辆间距大于等于枚举结果 mid 的元素;若找到,则计数器 cnt+=1 。对vector遍历一遍后用 cnt 与指定的目标 c 比较,若 cnt < c ,说明 mid 太大; 若 cnt > c ,说明 mid 太小; 若 cnt == mid ,说明 mid 为所求。

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int main(){

    unsigned int n, c;
    while(cin >> n >> c){
        vector<unsigned int> myVec;
        unsigned int temp, mid, left = 1, right = 1e9, cnt = 0, last, ans;
        for(unsigned int i = 0; i < n; i++){
            scanf("%d", &temp);
            myVec.push_back(temp);
        }
        sort(myVec.begin(), myVec.end());
        while(left <= right){
            mid = (left + right) / 2;
            cnt = 1;
            last = myVec[0];
            for(unsigned int i = 1; i < n; i++){
                if(myVec[i] - last >= mid){
                    cnt++;
                    last = myVec[i];
                }
                if(cnt > c)
                    break;
            }
            if(cnt < c){//mid is too big
                right = mid - 1;
            }
            else{//mid is too small or just it.
                ans = mid;//记录边界上的mid值。因为mid对应着答案不意味着循环的退出。所以用一个变量记录mid,
                left = mid + 1;//如果这个mid就是答案,那么下次循环的mid肯定不在此处,且循环会在那个mid处终止。
            }                  //若输出了mid,则得到错误答案。
        }                      //如果这个mid不是答案,那么由后续的作为答案的mid替换ans中的值,回到上述状态。
        cout << ans << endl;   //故ans一定表示正确的mid。
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值