文章目录
879. 盈利计划
可以看出来是一个dp的问题,并且给出了数据范围是100左右,因此可以猜到是 O ( n 3 ) O(n^3) O(n3)的复杂度的问题。但是这个问题的特点在于,是让你返回结果大于某个值的方案数量。
对于背包问题,有一种典型的问题是给定一个盈利,然后我们可以计算得到这个盈利的最大值。比如我们可以先问得到最大的收益是多少,然后再follow up得到最大收益的方案数量是多少。
对于这个题目,我们要求的大于某个值的方案数量,这就需要我们重新设计dp了。这里有一个挺巧妙的设计思路,dp[i][j]
直接表示了使用 i 个员工,可以实现收益至少是 j 的方案数量。这里因为至少是 j 因此我们求解时候就需要一个比较了。 int nk = Math.max(k - profit[i], 0);
这里是说,如果我们希望通过完成当前的任务实现至少k 的收益,我们之前需要多少收益才可以。
class Solution {
public int profitableSchemes(int G, int P, int[] group, int[] profit) {
int N = profit.length;
// dp[i][j] 表示i是人数,至少j是收益,
// 表示使用这些人,可以达到的最大收益
long[][] dp = new long[G + 1][P + 1];
//初始化
dp[0][0] = 1;
int MOD = 1000000007;
//三层dp循环
for (int i = 0; i < N; ++i) {
for (int j = G; j >= group[i]; --j) {
for (int k = 0; k <= P; ++k) {
//nk 表示new k 小于0 没有意义
int nk = Math.max(k - profit[i], 0);
// j个人至少k的收益,可以是少做当前项目,得到的
dp[j][k] += dp[j - group[i]][nk];
dp[j][k] %= MOD;
}
}
}
//最终返回
//System.out.println(Arrays.deepToString(dp));
long sum = 0;
for (int i = 0; i <= G; i++) {
sum = (sum + dp[i][P]) % MOD;
}
return (int)sum;
}
}