leetcode
leetcode 801 ~ 850
盈利计划

盈利计划

难度:

标签:

题目描述

代码结果

运行时间: 307 ms, 内存: 16.6 MB


/*
题目思路:
1. 使用动态规划来解决问题。
2. 定义一个三维数组 dp,dp[i][j][k] 表示前 i 个工作中,使用 j 个员工,获得至少 k 利润的方案数。
3. 初始化 dp[0][0][0] = 1,表示不使用任何员工且没有利润的情况。
4. 遍历每个工作,并更新 dp 数组。
5. 对每个工作,考虑两种情况:不选该工作和选该工作。
6. 最后统计 dp 数组中利润至少为 minProfit 的方案总数。
*/

import java.util.stream.IntStream;

public class ProfitableSchemesStream {
    public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
        int MOD = 1000000007;
        int length = group.length;
        int[][][] dp = new int[length + 1][n + 1][minProfit + 1];
        dp[0][0][0] = 1;

        for (int i = 1; i <= length; i++) {
            int members = group[i - 1];
            int earn = profit[i - 1];
            IntStream.rangeClosed(0, n).forEach(j -> IntStream.rangeClosed(0, minProfit).forEach(k -> {
                dp[i][j][k] = dp[i - 1][j][k];
                if (j >= members) {
                    dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - members][Math.max(0, k - earn)]) % MOD;
                }
            }));
        }

        return IntStream.rangeClosed(0, n).map(j -> dp[length][j][minProfit]).reduce(0, (a, b) -> (a + b) % MOD);
    }
}

解释

方法:

这个题解使用了动态规划和容斥原理。首先使用动态规划求出员工数不超过n的所有组合数,然后再求出利润小于minProfit的组合数。最后根据容斥原理,用员工数不超过n的组合数减去利润小于minProfit的组合数,得到员工数不超过n且利润不小于minProfit的组合数。

时间复杂度:

O(n^2+n*minProfit)

空间复杂度:

O(n*minProfit)

代码细节讲解

🦆
在动态规划的实现中,dp1数组初始化为dp1[0] = 1的原理是什么?其他位置为什么初始化为0?
在动态规划中,dp1数组用于计算不同的员工组合数,其中dp1[i]代表使用i个员工可以形成的组合数。初始化dp1[0] = 1是因为使用0名员工只有一种情况,即不使用任何员工。这是组合计算的基础,用于在后续迭代中累加新的员工组合。其他位置初始化为0的原因是,这些位置代表的是初始状态下使用相应数量的员工的组合数是未知的,因此从0开始计数。
🦆
对于dp1数组中的更新操作`dp1[i] += dp1[i-g]`,这里的逻辑是如何确保不会重复计算同一组工作人员的不同组合?
在更新dp1数组时,使用了从后向前的更新方式(即从n到g)。这种更新顺序确保在计算dp1[i]时,加入的dp1[i-g]是在没有考虑当前员工组g之前的状态,从而避免了组合的重复计算。这样的迭代顺序确保每种组合只被计算一次,防止同一组员工在同一轮更新中被重复考虑。
🦆
在处理`dp2`数组时,为什么要从后向前更新,即对于内层循环为什么是`range(minProfit-1, p-1, -1)`?
dp2数组负责计算在员工数不超过n且利润小于minProfit的组合数。在更新时从后向前(即从minProfit-1到p),是为了确保在更新当前利润j的组合数时,所引用的dp2[i-g][j-p]是未加入当前利润p之前的状态。这种从大到小的更新防止了当前轮次内的重复计算,确保每种利润组合都是基于前一状态的结果,避免了重复计算的错误。
🦆
题解中提到的容斥原理具体是如何应用的,在这个问题中它起到了什么作用?
容斥原理在这个问题中被用来计算最终符合条件的组合数。具体来说,首先计算所有可能的组合数(即员工数不超过n的组合数),然后计算不符合利润要求(即利润小于minProfit的组合数)。根据容斥原理,最终符合条件的组合数等于总的可能组合数减去不符合利润要求的组合数。这样可以有效地从所有可能的组合中排除那些不满足利润条件的情况,得到精确的符合要求的组合总数。

相关问题