有 n
名工人。 给定两个数组 quality
和 wage
,其中,quality[i]
表示第 i
名工人的工作质量,其最低期望工资为 wage[i]
。
现在我们想雇佣 k
名工人组成一个工资组。在雇佣 一组 k
名工人时,我们必须按照下述规则向他们支付工资:
1.对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。
2.工资组中的每名工人至少应当得到他们的最低期望工资。
给定整数 k
,返回 组成满足上述条件的付费群体所需的最小金额 。在实际答案的 10-5
以内的答案将被接受。
示例 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。
提示:
·n == quality.length == wage.length
·1 <= k <= n <= 104
·1 <= quality[i], wage[i] <= 104
题目大意:需找出k个工人,要求k个工人的工资都大于自身最低薪资,同时保证 给定工资:工作质量 相同。
分析:设选定的所有工人的给定工资:工作质量为p
(1)由于k个工人的给定工资:工作质量相同,因此p由选择工人中最大的最低工资:工作质量决定;
(2)由(1)可得选择的所有人的最低工资:工作质量都小于等于p,因此当先确定p再选工人时,只能从最低工资:工作质量小于等于p的工人中选择;
(3)由于p相同,选择的所有工人中工作质量越高的工人,给定的工资越高;
(4)由(2)和(3)可得,当p确定时,只需从最低工资:工作质量小于等于p的工人中按工作质量由低到高选择k人即可确定最小金额;
(5)由于题中p不确定,因此只需枚举所有工人的最低工资:工作质量,每次枚举使用(4)中的方法计算最小金额m,最后保留最小的m即为最终的最小金额。
思路优化:设工人i的最低工资:工作质量为p_i,确定第i个工人的p_i为p时的最低工资为m_i
(1)依据最低工资:工作质量对工人升序排序,排序后问题转换为:当确定第i个工人的最低工资:工作质量为p时,只需从前i-1个工人中寻找k-1个工作质量最低的工人即可;
(2)由于所选工人的p相同,因此最小金额=所选工人的工作质量之和*p;
(3)由(1)和(2)可得,对工人的最低工资:工作质量升序排序后,再进行遍历,同时遍历过程中用优先级队列维护前i-1个工人中最低的k-1个工作质量,并且用变量totalq维护最低的k-1个工作质量之和,则m_i=p_i*totalq。
class Solution {
public:
double mincostToHireWorkers(vector<int>& quality,vector<int>& wage,int k){
double m=DBL_MAX;
int N=quality.size();
int totalq=0;
priority_queue<int> q;//维护最低的k-1个工作质量
vector<int> index(N);//辅助排序的索引数组
iota(index.begin(),index.end(),0);//初始化索引数组
//对最低工资:工作质量升序排序
sort(index.begin(),index.end(),[&](int id1,int id2){
return quality[id1]*wage[id2]>quality[id2]*wage[id1];
});
for(int i=0;i<k-1;++i){
totalq+=quality[index[i]];
q.push(quality[index[i]]);
}
for(int i=k-1;i<N;++i){
int idx=index[i];
totalq+=quality[idx];
q.push(quality[idx]);
m=min(m,wage[idx]*1.0/quality[idx]*totalq);//计算最低工资
//维护最低的k-1个工作质量
totalq-=q.top();
q.pop();
}
return m;
}
};
//优化前的代码
// class worker{
// public:
// worker(int quality,double p):_quality(quality),_p(p){}
// int _quality;
// double _p;
// };
// bool operator<(const worker& w1,const worker& w2){
// return w1._quality<w2._quality;
// }
// class Solution {
// public:
// double findMinCost(vector<worker>& workers, int k,double p){
// double ans=0;
// int num=0;
// for(int i=0;i<workers.size()&&num<k;++i){
// if(workers[i]._p<=p){
// ++num;
// ans+=p*workers[i]._quality;
// }
// }
// if(num==k) return ans;
// return DBL_MAX;
// }
// double mincostToHireWorkers(vector<int>& quality,vector<int>& wage,int k){
// double m=DBL_MAX;
// int N=quality.size();
// unordered_set<double> ps;
// vector<worker> workers;
// workers.reserve(N);
// for(int i=0;i<N;++i){
// double p=wage[i]*1.0/quality[i];
// ps.insert(p);
// workers.emplace_back(quality[i],p);
// }
// sort(workers.begin(),workers.end());
// for(auto& ele:ps){
// m=min(m,findMinCost(workers,k,ele));
// }
// return m;
// }
// };