Leetcode每日一题857. 雇佣 K 名工人的最低成本

94 阅读1分钟
  • 难度:困难
  • 解题方法:数学、堆、优先队列
  • 排序:sort(q_w.begin(),q_w.end(),[&](int &a,int &b){ return quality[b]*wage[a]<quality[a]*wage[b]; });

题目描述

n 名工人。 给定两个数组 quality 和 wage ,其中,quality[i] 表示第 i 名工人的工作质量,其最低期望工资为 wage[i] 

现在我们想雇佣 k 名工人组成一个工资组。在雇佣 一组 k 名工人时,我们必须按照下述规则向他们支付工资:

对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。 工资组中的每名工人至少应当得到他们的最低期望工资。 给定整数 k ,返回 组成满足上述条件的付费群体所需的最小金额 。在实际答案的 10-5 以内的答案将被接受。。

数据范围

  • n == quality.length == wage.length
  • 1 <= k <= n <= 10^4
  • 1 <= quality[i], wage[i] <= 10^4

思路

  • 设我们选了a1,a2.....aka_1,a_2.....a_k名工人,他们的quality和为totalq,wage总和为totalw。
  • 由于个人所得工资和工作质量成正比,且不能低于最低工资保障,设第i个人,有quality[ai]totalqtotalwwage[ai]\frac{quality[a_i]}{totalq}*totalw\geq wage[a_i]
  • 变换表达式,有totalwwage[ai]quality[ai]totalqtotalw \geq \frac{wage[a_i]}{quality[a_i]}*totalq
  • 故要取得最小值totalw,在totalq一定的情况下,且要满足上式表达式,故要寻求组内wage[ai]quality[ai] \frac{wage[a_i]}{quality[a_i]}最大值,而totalq最小
  • 将下标数组q_w(既存储了数组下标)按比值wage[ai]quality[ai]\frac{wage[a_i]}{quality[a_i]}排序,升序。
  • 在组内,确定性因素是wage[ai]quality[ai]\frac{wage[a_i]}{quality[a_i]}最大值,而次要决定性因素是totalq的值,故用大根堆在进入下一遍历点是,去除顶堆最大值,要入下一点quality[ai+1]quality[a_i+1]的值,确保堆内总是k个数量。
class Solution {
public:
    double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int k) {
        int n=quality.size();
        vector<int>q_w(n,0);
        iota(q_w.begin(),q_w.end(),0);
        sort(q_w.begin(),q_w.end(),[&](int &a,int &b){
            return quality[b]*wage[a]<quality[a]*wage[b];
        });
        int totalq=0;
        priority_queue<int,vector<int>,less<int>>q;
        double ans=0xfffffffff;
        for(int i=0;i<n;i++){
            int index=q_w[i];
            if(i<k-1)totalq+=quality[index],q.push(quality[index]);
            else{
                totalq+=quality[index];q.push(quality[index]);
                double sum=((double)wage[index]/quality[index])*totalq;
                ans=min(ans,sum);
                totalq-=q.top();q.pop();
            }
        }
        return ans;
    }
};