概览
给定N
个工人,每个工人有一个quality
值和一个wage
值,要求在N
个工人中雇佣K
个人,并按照如下标准发放工资:
- 每个人被发放的工资
pay
与quality
的比值必须相同。 - 每个人被发放的工资
pay
必须大于wage
。
求总工资的最小值。
题解
首先,对题目中的两个条件进行解读。
由题中第一个条件可知:
选定的K
个人中,每人发放的实际工资pay
与quality
的比值相同。
定义价性比ratio = wage / quality
,表达每个工人单位quality
期望的工资,定义实际价性比ratio_ = pay / quality
,那么由题中第二个条件可知:
选定的K
个人中,每人发放的实际工资pay
与quality
的比值必须大于ratio
。
综上所述,可得本题关键性的信息:
选定的K
个人中,ratio_ >= max{ratio}
,即实际价性比不得低于雇佣的工人中最高的期望价性比。
又因为总工资cost = ratio_ * sum(quality)
,所以要使得总工资尽可能的小,就要使ratio_
和sum(quality)
尽可能小,因此可得具体的算法流程如下:
- 对所有人按价性比进行排序。
- 选择价性比最低的前
K
个人作为初始集,计算总工资。 - 从第
K + 1
个人开始,循环如下过程直至无人可以添加:- 踢出原集合中
quality
最大的工人,并添加该新工人。 - 重新计算
quality
的总和。 - 重新计算总工资,若小于当前最小值,则更新该值。
- 踢出原集合中
上述算法本质即遍历所有可能的价性比,找出最小的总工资。
复杂度分析
本题的空间复杂度为$O(N)$,但时间复杂度并不那么直观,需要逐步分析。
- 对所有人的价性比进行排序。($O(NlogN)$)
- 选择价性比最低的前
K
个人作为初始集,计算总工资。($O(N)$) - 从第
K + 1
个人开始,循环如下过程直至无人可以添加:($O(N)$)- 踢出原集合中
quality
最大的工人,并添加该新工人。($O(logN)$) - 重新计算
quality
的总和。($O(1)$) - 重新计算总工资,若小于当前最小值,则更新该值。($O(1)$)
- 踢出原集合中
其中步骤3.1的复杂度依赖于具体实现方式,使用优先队列实现可以保证复杂度为$O(logN)$。
步骤3.2只需要取出踢出的工人和新工人的quality
值即可计算,复杂度为常数时间。
步骤3.3中用新工人的ratio
作为总ratio_
进行计算,复杂度为常数时间。
综上所述,时间复杂度为$O(NlogN)$,空间复杂度为$O(N)$。