LeetCode 879 盈利计划[动态规划] HERODING的LeetCode之路

Posted HERODING23

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 879 盈利计划[动态规划] HERODING的LeetCode之路相关的知识,希望对你有一定的参考价值。

在这里插入图片描述解题思路:
依旧是动态规划的每日一题,这次又是三维dp数组并且可以优化的情况,dp[i][j][k]表示前i个工作量的情况下,使用员工数为j所能获得的最低利润k,依据这一点,在遍历时只用判断人数是否够用即可,统计sum时遍历所有人数情况(0,1,2…n),代码如下:

class Solution {
public:
    int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
        int len = group.size(), MOD = (int)1e9 + 7;
        vector<vector<vector<int>>> dp(len + 1, vector<vector<int>> (n + 1, vector<int>(minProfit + 1)));
        dp[0][0][0] = 1;
        for(int i = 1; i <= len; i ++) {
            for(int j = 0; j <= n; j ++) {
                for(int k = 0; k <= minProfit; k ++) {
                    // 如果人手不够了
                    if(group[i - 1] > j) {
                        dp[i][j][k] = dp[i - 1][j][k];
                    } else {
                        // 一定至少满足最少利润
                        dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - group[i - 1]][max(0, k - profit[i - 1])]) % MOD;
                    }
                }
            }
        }
        int sum = 0;
        // 累加选择员工人数0——n的各种情况
        for(int i = 0; i <= n; i ++) {
            sum = (sum + dp[len][i][minProfit]) % (MOD);
        }
        return sum;
    }
};

可以看到依然dp[i][][]依然只和dp[i - 1][][]有关,所以滚动数组的方式进行优化,注意仍要从后往前遍历,保持i-1状态的的数不被更新,代码如下:

class Solution {
public:
    int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
        int len = group.size(), MOD = (int)1e9 + 7;
        vector<vector<int>> dp(n + 1, vector<int>(minProfit + 1));
        dp[0][0] = 1;
        for(int i = 1; i <= len; i ++) {
            for(int j = n; j >= 0; j --) {
                for(int k = minProfit; k >= 0; k --) {
                    // 如果人手不够了
                    if(group[i - 1] <= j) {
                        // 一定至少满足最少利润
                        dp[j][k] = (dp[j][k] + dp[j - group[i - 1]][max(0, k - profit[i - 1])]) % MOD;
                    }
                }
            }
        }
        int sum = 0;
         for(int i = 0; i <= n; i ++) {
            sum = (sum + dp[i][minProfit]) % (MOD);
        }
        return sum;
    }
};

还可以进一步优化,省去了累加的问题,在初始化的时候需要把所有的人数从0——n都要更新为1,这样最后不需要考虑人数的问题,代码如下:

class Solution {
public:
    int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
        int len = group.size(), MOD = (int)1e9 + 7;
        vector<vector<int>> dp(n + 1, vector<int>(minProfit + 1));
        for (int i = 0; i <= n; i++) {
            dp[i][0] = 1;
        }
        for(int i = 1; i <= len; i ++) {
            for(int j = n; j >= 0; j --) {
                for(int k = minProfit; k >= 0; k --) {
                    // 如果人手不够了
                    if(group[i - 1] <= j) {
                        // 一定至少满足最少利润
                        dp[j][k] = (dp[j][k] + dp[j - group[i - 1]][max(0, k - profit[i - 1])]) % MOD;
                    }
                }
            }
        }
        return dp[n][minProfit];
    }
};

以上是关于LeetCode 879 盈利计划[动态规划] HERODING的LeetCode之路的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 879. 盈利计划(dp)

LeetCode 879. 盈利计划(动规典范题!)/ 牛客:找零 / 机器人跳跃问题

[H背包] lc879. 盈利计划(二维费用背包+难题+状态定义)

879. 盈利计划(多维背包问题)

879. 盈利计划(多维背包问题)

879. 盈利计划