# [LeetCode 857. Minimum Cost to Hire K Workers ( HARD ) ](https://leetcode.com/problems/minimum-cost-to-hire-k-workers/)
:::success
[相似題 : 1383. Maximum Performance of a Team](https://hackmd.io/BaUbRo4vTdi69qpEyTFvEg)
:::
>There are **`n`** workers. The i-th worker has a **`quality[i]`** and a minimum wage expectation **`wage[i]`**.
>
>Now we want to hire **exactly `k`** workers to form a paid group. When hiring a group of k workers, we must pay them according to the following rules:
>
>* Every worker in the paid group should be paid in the ratio of their quality compared to other workers in the paid group.
>* Every worker in the paid group must be paid at least their minimum wage expectation.
>
>Return the least amount of money needed to form a paid group satisfying the above conditions.
:::info
**Example 1:**
**Input:** quality = [10,20,5], wage = [70,50,30], k = 2
**Output:** 105.00000
**Explanation:** We pay 70 to 0-th worker and 35 to 2-th worker.
:::
:::info
**Example 2:**
**Input:** quality = [3,1,10,10,1], wage = [4,8,2,2,7], k = 3
**Output:** 30.66667
**Explanation:** We pay 4 to 0-th worker, 13.33333 to 2-th and 3-th workers seperately.
:::
:::warning
**Constraints:**
* 1 <= k <= n <= 10000, where n = quality.length = wage.length
* 1 <= quality[i] <= 10000
* 1 <= wage[i] <= 10000
* Answers within 10^-5^ of the correct answer will be considered correct.
:::
---
### Approach 1 : Max Heap ( Priority Queue ) :book:
**`32ms ( 87.22% )`** **`O()`**
* 根據 `Rule 1` 因為要讓被雇用的人獲得的薪水**比例相同**,所以希望**比例越小越好**,假設 **`ratio = wage / quality`**。
再根據 `Rule 2` 可以知道,`SumOfQuality` 也是**越小越好**,所以透過 `max_heap` 刪除最大的 `quality`。
* 將 **`ratio & quality`** 存入 **`pair`** 中,並將 `ratio` 的部分由小到大進行 **`sort`**。
* **`SumOfQuality`** 紀錄當前 `quality` 總和,**`ans`** 紀錄當前最小答案。
* 目標找出最少的花費 **`money = SumOfQuality * ratio[i]`**。 ( 因為 `ratio` 是由小到大排序,所以只須考慮 `SumOfQuality & ratio[i]`)。
* **`max_heap`** 儲存當前使用的 `quality`。
>* 每次都將 `quality` 放入 `heap` 中,**`SumOfQuality += quality[i]`**。
>* 當 `size > k` 時,**`SumOfQuality -= heap.top()`**,並 `pop top of the value`。
>* 當 `size == k` 時才能判斷 **`ans = min(ans, SumOfQuality * ratio[i])`**。
>( 因為需要**剛剛好雇用 `k` 個員工**,所以當 `size < k` 時就先判斷會錯誤 )。
---
>**EXAMPLE :**
>**`quality = [10, 20, 5]`、`wage = [70, 50, 30]`、`k = 2`**。
> ---> **`ratio = [7, 2.5, 6]`**。
> 1. **sort ratio** :
> ---> `r = [2.5, 6, 7]`。
> ---> `q = [20, 5, 10]`。
> 2. **Max Heap** :
> **`SumOfSpeed = 0`**、**`ans = 999999999`**。
>> * i = 0 ---> heap = `({2.5, 20})` ---> `size < k`。
>> **`SumOfQuality = 20`**、**`ans = 999999999`**。
>> * i = 1 ---> heap = `({2.5, 20}, {6, 5})`。
>> **`SumOfQuality = 25`**、**`money = 25 * 6 = 150`**、**`ans = 150`**。 :+1:
>> * i = 2 ---> heap = `({7, 10}, {6, 5})`。
>> **`SumOfQuality = 15`**、**`money = 15 * 7 = 105`**、**`ans = 105`**。 :+1:
```cpp=1
class Solution {
public:
double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int k) {
vector<pair<double, int> > worker; // ratio, quality
for(int i=0; i<quality.size(); i++){
worker.push_back({wage[i]*1.0/quality[i], quality[i]});
}
sort(worker.begin(), worker.end());
// heap //
priority_queue<int > heap; // quality
int SumOfQuality = 0;
double ans = 999999999;
for(int i=0; i<worker.size(); i++){
SumOfQuality += worker[i].second;
heap.push(worker[i].second);
if(heap.size() > k){
SumOfQuality -= heap.top();
heap.pop();
}
if(heap.size() == k) ans = min(ans, SumOfQuality * worker[i].first);
}
return ans;
}
};
```