879. 盈利计划
集团里有 n 名员工,他们可以完成各种各样的工作创造利润。
第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。
工作的任何至少产生 minProfit 利润的子集称为 盈利计划 。并且工作的成员总数最多为 n 。
有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7 的值。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/profitable-schemes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
动态规划
class Solution {
private static final int MOD = 1000000007;
public int profitableSchemes(int peoples, int minProfit, int[] group, int[] profit) {
int groups = group.length;
int[][][] dp = new int[groups + 1][peoples + 1][minProfit + 1];
dp[0][0][0] = 1;
for (int i = 1; i <= groups; ++i) {
for (int j = 0; j <= peoples; ++j) {
for (int k = 0; k <= minProfit; ++k) {
if (j >= group[i - 1]) {
dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - group[i - 1]][Math.max(0, k - profit[i - 1])]) % MOD;
} else {
dp[i][j][k] = dp[i - 1][j][k];
}
}
}
}
int ans = 0;
for (int j = 0; j <= peoples; ++j) {
ans = (ans + dp[groups][j][minProfit]) % MOD;
}
return ans;
}
}
动态规划 + 状态压缩
class Solution {
private static final int MOD = 1000000007;
public int profitableSchemes(int peoples, int minProfit, int[] group, int[] profit) {
int groups = group.length;
int[][] dp = new int[peoples + 1][minProfit + 1];
for (int i = 0; i <= peoples; ++i) {
dp[i][0] = 1;
}
for (int i = 1; i <= groups; ++i) {
for (int j = peoples; j >= group[i - 1]; --j) {
for (int k = minProfit; k >= 0; --k) {
dp[j][k] = (dp[j][k] + dp[j - group[i - 1]][Math.max(0, k - profit[i - 1])]) % MOD;
}
}
}
return dp[peoples][minProfit];
}
}
心之所向,素履以往 生如逆旅,一苇以航

浙公网安备 33010602011771号