879. Profitable Schemes
題目網址:https://leetcode.cn/problems/profitable-schemes/
題意:集團里有
n名員工, 他們可以完成各種各樣的工作創造利潤。第
i種工作會產生profit[i]的利潤, 它要求group[i]名成員共同參與。如果成員參與了其中一項工作, 就不能參與另一項工作。選取一些工作, 這些工作需產生至少
minProfit的利潤, 且工作的成員總數不得超過n。有多少種方案可以選擇?因為答案很大, 所以返回結果 mod
$10^9 + 7$的值即可。

Solution 1:
想法:利用 DP, 本題有兩種容量, 因此使用三維 DP
1. 定義狀態:
- 首先, 會在
group、profit前先加上一個0, 代表什麼元素都沒有的狀態dp[i][j][k]:前i個工作中「恰好」選擇了j個員工, 並滿足利潤為「至少」為k的方案數2. 得到轉移方程:
- 第
i個工作有「選 or 不選」兩種選擇:
若不選, 則要用前
i - 1個工作完成選擇j個員工, 並滿足最小利潤為k
➔dp[i][j][k] = dp[i - 1][j][k]若要選, 假設第
i個工作需person個員工, 且能創造earn利潤。則前i - 1個工作需選擇j - person個員工, 且至少需創造k - earn利潤
➔dp[i][j][k] = dp[i - 1][j - person][k - earn]
- 由於我們定義的
dp[i][j][k]是利潤「至少」為k, 而不是利潤「恰好」為k, 故上述的第三維應改為max(0, k - earn)而不是k - earn- 理由:若
earn > k, 代表光是第i個工作的利潤就超過要求k了, 但我們題目要求的是「至少」, 也就是說如果要求利潤「至少」為k, 則利潤為k、k + 1、k + 2、… 也都是滿足條件的- e.g. 若
earn > k, 則應選擇第i個工作(假設沒超過人數上限), 並把該方案數加到dp[i][j - person][0]中, 代表前i - 1個工作就算利潤為0也沒關係, 只要選了第i個工作就能滿足利潤至少為k➔
dp[i][j][k] = dp[i - 1][j - person][max(0, k - earn)]3. 初始化:
dp[0][0][0]:當沒有工作時, 選擇0個員工, 並滿足利潤為「至少」為0的方案數為1(什麼都不選也是一種方案)
➔dp[0][0][0] = 1題目要求的是所有工作中, 利潤至少為
minProfit, 且工作的成員總數「不得超過」n, 因此選擇的人數可以是0、1、…、n, 故答案要對所有可能人數的方案數進行加總
➔res = (res + dp[m][j][minProfit]), for0 ≤ j ≤ n
class Solution { |
- time:$O(m \cdot n \cdot minProfit)$ ➔ for loop
- space:$O(m \cdot n \cdot minProfit)$ ➔
dp
Solution 2:
想法:改進 Solution 1, 由於
dp[i][j][k]只會用到上一列的狀態, 因此只需保存上一列的狀態即可
class Solution { |
- time:$O(m \cdot n \cdot minProfit)$ ➔ for loop
- space:$O(n \cdot minProfit)$ ➔
dp