题目描述:
集团里有 n 名员工,他们可以完成各种各样的工作创造利润。
第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。
工作的任何至少产生 minProfit 利润的子集称为 盈利计划 。并且工作的成员总数最多为 n 。
有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7 的值。
示例 1:
输入:n = 5, minProfit = 3, group = [2,2], profit = [2,3]
输出:2
解释:至少产生 3 的利润,该集团可以完成工作 0 和工作 1 ,或仅完成工作 1 。
总的来说,有两种计划。
题解:
由于我们定义的第二维是工作利润至少为 k 而不是 工作利润恰好为 k,因此上述状态转移方程中右侧的第二维是 max(0,k-profit[i]), 而不是 k - profit[i]。读者可以思考这一步的妙处所在。
类似于0,1背包的写法,只是维度含义定义不同,不太能考虑到
dp[i][j]:表示 i 个人,至少产生 j 利润的方法数。
题源:https://leetcode-cn.com/problems/profitable-schemes/
题解:https://leetcode-cn.com/problems/profitable-schemes/solution/cdong-tai-gui-hua-by-heroding-8q6w/
class Solution { public: int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) { int l=profit.size(); int dp[105][105]; int mod=(int)1e9+7; memset(dp,0,sizeof(dp)); for(int i=0;i<=n;i++) dp[i][0]=1; //这一步决定了,最后的结果需不需要重新累加 for(int i=0;i<l;i++) for (int ren=n;ren>=group[i];ren--) for (int pro=minProfit;pro>=0;pro--) dp[ren][pro]=( dp[ren][pro] + dp[ren-group[i]][max(0,pro-profit[i])] ) % mod; return dp[n][minProfit]; } };