题目:集团里有 n 名员工,他们可以完成各种各样的工作创造利润。
第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。
工作的任何至少产生 minProfit 利润的子集称为 盈利计划 。并且工作的成员总数最多为 n 。
有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7 的值。
示例:
输入:n = 5, minProfit = 3, group = [2,2], profit = [2,3]
输出:2
代码:
class Solution(object):
def profitableSchemes(self, n, minProfit, group, profit):
"""
:type n: int
:type minProfit: int
:type group: List[int]
:type profit: List[int]
:rtype: int
"""
total = 0
#计算出工作类型总数
l = len(group)
#创建一个三维列表dp[i][j][k],i代表选取前i个工作,j代表需要j个员工,k代表至少可达利润k
#用for循环创建列表,用[0]*n方法创建列表会导致后面赋值错误
dp = [[[0] * (minProfit + 1) for _ in range(n + 1)] for _ in range(l + 1)]
#表示选取0个工作,0个员工,利润为0的方案有一种
dp[0][0][0] = 1
for i in range(1,l+1): #遍历前i个工作
for j in range(n+1): #遍历n个员工
for k in range(minProfit+1): #遍历利润从0至minProfit
if j < group[i-1]:
#根据01背包问题可知,如果当前人数不满足第i项工作所需人数,则不能完成此工作,则有此等式关系
dp[i][j][k] = dp[i-1][j][k]
else:
#若当前人数满足第i项工作所需人数,则可以完成此工作,则有此等式关系。
#由于题目要求只需要利润大于等于k即可,所以此处用max(0,k-profit[i-1])而不是k-profit[i-1]
dp[i][j][k] = dp[i-1][j][k]+dp[i-1][j-group[i-1]][max(0,k-profit[i-1])] #若当前人数满足第i项工作所需人数,则有此等式关系。注:由于题目要求利润为至少,只需要利润大于等于k即可,所以此处用max(0,k-profit[i-1])而不是k-profit[i-1]
for j in range(n+1):
#对不同员工数达到的要求最低利润种类进行求和
total += dp[l][j][minProfit]
return total%(10**9+7)
流程图: