LeetCode 879. 盈利计划
879. 盈利計劃
本題與經典背包問題非常相似。兩者不同點在于經典背包問題只有一種容量限制,而本題卻有兩種限制:集團員工人數上限 n,以及工作產生的利潤下限 minProfit。
通過經典背包問題的練習,我們已知經典背包問題可以使用二維動態規劃求解:兩個維度分別代表物品和容量的限制標準。
對于本題上述的兩種限制,我們可以想到使用三維動態規劃求解。
本題解法的三個維度分別為:當前可選擇的工作,已選擇的小組員工人數,以及目前狀態的工作獲利下限。
根據上述分析,我們可以定義一個三維數組 dp 作為動態規劃的狀態,其中 dp[i][j][k] 表示在前 i 個工作中選擇了 j 個員工,并且滿足工作利潤至少為 k 的情況下的盈利計劃的總數目。假設 group 數組長度為 len,那么不考慮取模運算的情況下,最終答案為:
所以我們可以新建一個三維數組 dp[len+1][n+1][minProfit+1],初始化 dp[0][0][0]=1。接下來分析狀態轉移方程,對于每個工作 i,我們根據當前工作人數上限 j,有能夠開展當前工作和無法開展當前工作兩種情況:
- 如果無法開展當前工作 i,那么顯然:
- 如果能夠開展當前工作 i,設當前小組人數為 group[i],工作獲利為 profit[i],那么不考慮取模運算的情況下,則有:
由于我們定義的第三維是工作利潤至少為 k 而不是 工作利潤恰好為 k,因此上述狀態轉移方程中右側的第三維是 max(0,k?profit[i]) 而不是 k?profit[i]。讀者可以思考這一步的妙處所在。
Code
Python
class Solution:def profitableSchemes(self, n: int, minProfit: int, group: List[int], profit: List[int]) -> int:MOD = 10 ** 9 + 7length = len(group)dp = [[[0] * (minProfit + 1) for _ in range(n + 1)] for _ in range(length + 1)]dp[0][0][0] = 1for i in range(1, length + 1):# 第 i 個工作要求參與的員工數量和會產生的利潤members, earn = group[i - 1], profit[i - 1]for j in range(n + 1):for k in range(minProfit + 1):if j < members: # 如果當前工作人數上限小于需要求參與的員工數量則無法開展此工作dp[i][j][k] = dp[i - 1][j][k]else:dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - members][max(0, k - earn)]) % MODtotal = sum(dp[length][j][minProfit] for j in range(n + 1))return total % MOD作者:LeetCode-Solution
鏈接:https://leetcode-cn.com/problems/profitable-schemes/solution/ying-li-ji-hua-by-leetcode-solution-3t8o/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的LeetCode 879. 盈利计划的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EduCoder Linux之文件打包和
- 下一篇: EduCoder 机器学习 逻辑回归