【每日一题】leetcode杂题宣讲

文章目录

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;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值