879. 盈利计划

2024/03/25 leetcode 共 1471 字,约 5 分钟

title

problem link

集团里有 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 。
总的来说,有两种计划。

示例 2:

输入:n = 10, minProfit = 5, group = [2,3,5], profit = [6,7,8]
输出:7
解释:至少产生 5 的利润,只要完成其中一种工作就行,所以该集团可以完成任何工作。
有 7 种可能的计划:(0),(1),(2),(0,1),(0,2),(1,2),以及 (0,1,2) 。

提示:

  • 1 <= n <= 100
  • 0 <= minProfit <= 100
  • 1 <= group.length <= 100
  • 1 <= group[i] <= 100
  • profit.length == group.length
  • 0 <= profit[i] <= 100

solution

记忆化搜索dfs会超时,DP递推就不会超时。 group排序没啥用,但可以用来剪枝,这里没剪枝。

这里的profit和人数看做体积,人数为至多,profit为至少。是个同时有至多、至少的好题目。

可以空间优化少一维。

先dfs,再递推容易想。

class Solution:
    def profitableSchemes(self, n: int, minProfit: int, group: List[int], profit: List[int]) -> int:
        MOD = int(1e9 + 7)
        d = [(group[i], profit[i]) for i in range(len(group))]
        d.sort(reverse=True)
        group = [v[0] for v in d]
        profit = [v[1] for v in d]
        import functools
        @functools.lru_cache(None)
        def f(i, c, p):
            if i == 0:
                if c >= 0 and p <= 0:
                    return 1
                return 0
            res = 0
            # not select
            res += f(i - 1, c, p)
            # select
            if c - group[i - 1] >= 0:
                res += f(i - 1, c - group[i - 1], p - profit[i - 1])
            res %= MOD
            return res

        # ans = f(len(group), n, minProfit)
        # f.cache_clear()
        # return ans
        dp = [[0 for _ in range(minProfit + 1)] for _ in range(n + 1)]
        for i in range(n + 1):
            dp[i][0] = 1
        for i in range(1, len(group) + 1):
            for c in range(n, -1, -1):
                if c - group[i - 1] >= 0:
                    for p in range(minProfit, -1, -1):
                        dp[c][p] += dp[c - group[i - 1]][max(0, p - profit[i - 1])]
                        dp[c][p] %= MOD
        # print(dp)
        # assert ans == dp[n][minProfit]
        return dp[n][minProfit]

Search

    Table of Contents