- 难度:困难
- 解题方法:数学、堆、优先队列
- 排序:
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
思路
- 设我们选了名工人,他们的quality和为totalq,wage总和为totalw。
- 由于个人所得工资和工作质量成正比,且不能低于最低工资保障,设第
i个人,有 - 变换表达式,有
- 故要取得最小值totalw,在totalq一定的情况下,且要满足上式表达式,故要寻求组内最大值,而totalq最小
- 将下标数组q_w(既存储了数组下标)按比值排序,升序。
- 在组内,确定性因素是最大值,而次要决定性因素是totalq的值,故用大根堆在进入下一遍历点是,去除顶堆最大值,要入下一点的值,确保堆内总是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;
}
};