LeetCode 雇佣K名工人的最低成本(优先队列)

版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/90899961

有 N 名工人。 第 i 名工人的工作质量为 quality[i] ,其最低期望工资为 wage[i] 。

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

对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。
工资组中的每名工人至少应当得到他们的最低期望工资。
返回组成一个满足上述条件的工资组至少需要多少钱。

示例 1:

输入: quality = [10,20,5], wage = [70,50,30], K = 2
输出: 105.00000
解释: 我们向 0 号工人支付 70,向 2 号工人支付 35。

示例 2:

输入: quality = [3,1,10,10,1], wage = [4,8,2,2,7], K = 3
输出: 30.66667
解释: 我们向 0 号工人支付 4,向 2 号和 3 号分别支付 13.33333。

提示:

1 <= K <= N <= 10000,其中 N = quality.length = wage.length
1 <= quality[i] <= 10000
1 <= wage[i] <= 10000
与正确答案误差在 10^-5 之内的答案将被视为正确的。

\color{blue}思路分析: 首先我们计算每个工人的性价比costPerformance(即预期工资wage[i] / 工作质量 quality[i],也即单位工作量的价格),因此costPerformance越低表示性价比越高。
然后按照 单位工作量的价格 进行升序排序。并且使用辅助优先队列,选出K名工人。
假设K名工人的工作质量总和为sum,而我们又要满足所选工人的工资不得低于各自的预期,则costPerformance应该取这K名工人的最大值(性价比最低)来计算总工资sum * costPerformance。
并且当costPerformance一定时,我们得使工作质量总和为sum尽可能的小,才能降低总工资。

//自定义工人结构体
struct MyWorker{
    int quality;//质量
    double costPerformance;//性价比:单位工作质量需要的价格(性价比越高,数值越小)
    MyWorker(int _quality, double _costPerformance){
        quality = _quality;
        costPerformance = _costPerformance;
    }
    //重载小于号,用于按照 性价比:单位工作质量需要的价格 升序排序
    bool operator < (const MyWorker &myWorker){
        return costPerformance < myWorker.costPerformance;
    }
};
class Solution {
public:
    double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int K) {
        int N = quality.size();
        vector<MyWorker> myWorkerVec;//存储所有工人的信息
        for (int i = 0; i < N; ++i){
            myWorkerVec.push_back(MyWorker(quality[i], 1.0 * wage[i] / quality[i]));
        }
        sort(myWorkerVec.begin(), myWorkerVec.end());//按照性价比递减排序(性价比越高,数值越小)
        double result = INT_MAX, sum = 0;
        priority_queue<int> maxHeap;//大顶堆
        //从性价比高的工人向性价比低的工人扫描
        for (const auto& worker: myWorkerVec) {
            sum += worker.quality;//worker的工作质量放入总工作质量
            maxHeap.emplace(worker.quality);//worker的工作质量放入优先队列
            //如果工人超过了K,则移除最大工作量的工人(即优先队列的顶端)
            if (maxHeap.size() > K) {
                sum -= maxHeap.top();
                maxHeap.pop();
            }
            //由于扫描过程是从性价比高的工人向性价比低的工人扫描,并且我们得不低于每个人的预期工资,
            //所以得按照最低性价比(单位工作质量需要的最高价格),就是当前最后一名工人worker的性价比计算总工资
            if (maxHeap.size() == K) {
                result = min(result, sum * worker.costPerformance);
            }
        }
        return result;
    }
};

在这里插入图片描述
性价比的概念可能会有些绕,只要记住它的本质是 “单位工作量的价格” 就比较好理解。

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/90899961