贪心+二分的分组算法题

题目:将n个同学分为k个队伍,使队伍的极差最小并返回最小的极差

不断检查是否能将n个同学分为<=k个队伍,如果可以缩减右边界(右边界是极差)

如果不行,扩大左边界(mid+1)

假设 cnt 为贪心得到的解,ans 为整体最优解,因为一定可以把一个组分成多个组,所以满足 cnt >= ans 的条件,而排序之后在每组最大差值既定的条件下,贪心会尽可能把符合条件的同学收入到一个组里,直至装不了才会开一个新组,便满足 cnt <= ans 的条件。然后就可以得到 cnt == ans 的结论,所以贪心就是整体最优解。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool check(vector<int>& heights, int k, int max_diff) {
    int cnt = 1, cur = heights[0], n = heights.size();
    for (int i = 1; i < n; i++)
    {
        if (heights[i] - cur > max_diff)//如果超过设定边界就要开新队伍
        {
            cnt++;
            cur = heights[i];
        }
    }
    return cnt <= k; //队伍总数符合要求吗?
}
int main() {
    int n, k;
    cin >> n >> k;
    vector<int> heights(n);
    for (int i = 0; i < n; ++i) cin >> heights[i];
    sort(heights.begin(), heights.end());
    int l = 0, r = heights[n - 1] - heights[0];//左闭右开的区间
    while (l < r) 
    {
        int mid = l + (r - l) / 2;
        if (check(heights, k, mid)) r = mid;
        else l = mid + 1;
    }
    cout << l << endl;
    return 0;
}

贪心贪心,贪的是队伍极差,不断将队伍极差缩小来取到最小

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值