其他分享
首页 > 其他分享> > LeetCode/雇佣K名工人的最低成本

LeetCode/雇佣K名工人的最低成本

作者:互联网

有 n 名工人, 给定两个数组 quality 和 wage ,其中
quality[i] 表示第 i 名工人的工作质量,其最低期望工资为 wage[i]
现在我们想雇佣 k 名工人组成一个工资组,满足一下条件

  1. 对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。
  2. 工资组中的每名工人至少应当得到他们的最低期望工资

返回应支付的最少工资

1. 贪心算法

对于某一组,通过工作质量占比计算得到工资占比,期望工资除以工资占比,取最大值,从而可以算出满足所有人条件的最小总工资

\[totalw>=totalq×\frac{wage[i]}{quality[i]} \]

\(实际上,对于某一组,totalq是固定的,总工资跟\frac{wage[i]}{quality[i]}最大值相关\)
当我们以某一个工人 x 作为一个工资组中权重最高时
工资组中其他人员只需要在权重小于工人 x 的集合中选择工作质量最少的 k−1 名工人来组成工资组即可
此时得到的总工资最少

//要尽可能使计算量小,需要减少重复运算
//首先按权重进行升序排列,这里记录对应序号,因为要用到对应工作质量和价格,这样就可以从左往右进行遍历挑选当前组最大权重值
//因为还要挑选k-1的最小工作质量,这里用优先队列记录,每次淘汰掉最大值即可,避免重复查找
class Solution {
public:
    double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int k) {
        int n = quality.size();
        vector<int> h(n, 0);//记录序号映射
        iota(h.begin(), h.end(), 0);//产生从0开始连续数值
        sort(h.begin(), h.end(), [&](int& a, int& b) {//按质量工资比重从小到大重排序列
            return quality[a] * wage[b] > quality[b] * wage[a];});
        double res = 1e9;
        double totalq = 0.0;
        priority_queue<int, vector<int>, less<int>> q;//降序优先队列,第一个元素最大值
        for (int i = 0; i < k - 1; i++) {
            totalq += quality[h[i]];//计算总工作质量
            q.push(quality[h[i]]);//工作质量入队列,由小到大排
        }
        for (int i = k - 1; i < n; i++) {//从小到大选取权重
            int idx = h[i];
            totalq += quality[idx];//计算当前总工作量
            q.push(quality[idx]);//入优先队列,方便后续选取k-1个最小工作质量
            double totalc = ((double) wage[idx] / quality[idx]) * totalq;//计算当前最小价格
            res = min(res, totalc);//记录更新结果
            totalq -= q.top();//更新前k-1个的总工作质量
            q.pop();//保持k-1个值
        }
        return res;
    }
};

标签:wage,int,工资,最低,totalq,雇佣,质量,quality,LeetCode
来源: https://www.cnblogs.com/929code/p/16683319.html