879. 盈利计划 力扣 动态规划 难

题目描述:

集团里有 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];
    }
};
原文地址:https://www.cnblogs.com/stepping/p/14882489.html