Profitable Schemes
HardUpdated: Aug 2, 2025
Practice on:
Profitable Schemes Problem
Problem
There is a group of n members, and a list of various crimes they could commit. The ith crime generates a profit[i] and requires group[i] members to participate in it. If a member participates in one crime, that member can't participate in another crime.
Let's call a profitable scheme any subset of these crimes that generates at least minProfit profit, and the total number of members participating in that subset of crimes is at most n.
Return the number of schemes that can be chosen. Since the answer may be very large, return it modulo 10^9 + 7.
Examples
Example 1:
Input:
n = 5, minProfit = 3, group = [2,2], profit = [2,3]
Output:
2
Explanation: To make a profit of at least 3, the group could either commit crimes 0 and 1, or just crime 1.
In total, there are 2 schemes.
Example 2:
Input:
n = 10, minProfit = 5, group = [2,3,5], profit = [6,7,8]
Output:
7
Explanation: To make a profit of at least 5, the group could commit any crimes, as long as they commit one.
There are 7 possible schemes: (0), (1), (2), (0,1), (0,2), (1,2), and (0,1,2).
Solution
Method 1 – Dynamic Programming (Knapsack)
Intuition
Use dynamic programming to count the number of ways to select crimes such that the total number of members does not exceed n and the total profit is at least minProfit.
Approach
- Use a DP table dp[i][j][k] where i is the number of crimes considered, j is the number of members used, and k is the profit achieved (capped at minProfit).
- For each crime, update the DP table by considering both including and excluding the crime.
- The answer is the sum of all dp[len][j][minProfit] for j in 0..n.
Code
C++
class Solution {
public:
int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
int MOD = 1e9+7, len = group.size();
vector<vector<vector<int>>> dp(len+1, vector<vector<int>>(n+1, vector<int>(minProfit+1)));
dp[0][0][0] = 1;
for (int i = 1; i <= len; ++i) {
int g = group[i-1], p = profit[i-1];
for (int j = 0; j <= n; ++j) {
for (int k = 0; k <= minProfit; ++k) {
dp[i][j][k] = dp[i-1][j][k];
if (j >= g) {
int newProfit = min(minProfit, k + p);
dp[i][j][newProfit] = (dp[i][j][newProfit] + dp[i-1][j-g][k]) % MOD;
}
}
}
}
int res = 0;
for (int j = 0; j <= n; ++j) res = (res + dp[len][j][minProfit]) % MOD;
return res;
}
};
Go
func profitableSchemes(n int, minProfit int, group []int, profit []int) int {
mod := int(1e9+7)
len := len(group)
dp := make([][][]int, len+1)
for i := range dp {
dp[i] = make([][]int, n+1)
for j := range dp[i] {
dp[i][j] = make([]int, minProfit+1)
}
}
dp[0][0][0] = 1
for i := 1; i <= len; i++ {
g, p := group[i-1], profit[i-1]
for j := 0; j <= n; j++ {
for k := 0; k <= minProfit; k++ {
dp[i][j][k] = dp[i-1][j][k]
if j >= g {
newProfit := k + p
if newProfit > minProfit { newProfit = minProfit }
dp[i][j][newProfit] = (dp[i][j][newProfit] + dp[i-1][j-g][k]) % mod
}
}
}
}
res := 0
for j := 0; j <= n; j++ { res = (res + dp[len][j][minProfit]) % mod }
return res
}
Java
class Solution {
public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
int MOD = 1_000_000_007, len = group.length;
int[][][] dp = new int[len+1][n+1][minProfit+1];
dp[0][0][0] = 1;
for (int i = 1; i <= len; ++i) {
int g = group[i-1], p = profit[i-1];
for (int j = 0; j <= n; ++j) {
for (int k = 0; k <= minProfit; ++k) {
dp[i][j][k] = dp[i-1][j][k];
if (j >= g) {
int newProfit = Math.min(minProfit, k + p);
dp[i][j][newProfit] = (dp[i][j][newProfit] + dp[i-1][j-g][k]) % MOD;
}
}
}
}
int res = 0;
for (int j = 0; j <= n; ++j) res = (res + dp[len][j][minProfit]) % MOD;
return res;
}
}
Kotlin
class Solution {
fun profitableSchemes(n: Int, minProfit: Int, group: IntArray, profit: IntArray): Int {
val MOD = 1_000_000_007
val len = group.size
val dp = Array(len+1) { Array(n+1) { IntArray(minProfit+1) } }
dp[0][0][0] = 1
for (i in 1..len) {
val g = group[i-1]; val p = profit[i-1]
for (j in 0..n) {
for (k in 0..minProfit) {
dp[i][j][k] = dp[i-1][j][k]
if (j >= g) {
val newProfit = minOf(minProfit, k + p)
dp[i][j][newProfit] = (dp[i][j][newProfit] + dp[i-1][j-g][k]) % MOD
}
}
}
}
var res = 0
for (j in 0..n) res = (res + dp[len][j][minProfit]) % MOD
return res
}
}
Python
class Solution:
def profitableSchemes(self, n: int, minProfit: int, group: list[int], profit: list[int]) -> int:
MOD = 10**9+7
len_ = len(group)
dp = [[[0]*(minProfit+1) for _ in range(n+1)] for _ in range(len_+1)]
dp[0][0][0] = 1
for i in range(1, len_+1):
g, p = group[i-1], profit[i-1]
for j in range(n+1):
for k in range(minProfit+1):
dp[i][j][k] = dp[i-1][j][k]
if j >= g:
newProfit = min(minProfit, k + p)
dp[i][j][newProfit] = (dp[i][j][newProfit] + dp[i-1][j-g][k]) % MOD
return sum(dp[len_][j][minProfit] for j in range(n+1)) % MOD
Rust
impl Solution {
pub fn profitable_schemes(n: i32, min_profit: i32, group: Vec<i32>, profit: Vec<i32>) -> i32 {
let n = n as usize;
let min_profit = min_profit as usize;
let len = group.len();
let mut dp = vec![vec![vec![0; min_profit+1]; n+1]; len+1];
dp[0][0][0] = 1;
for i in 1..=len {
let g = group[i-1] as usize;
let p = profit[i-1] as usize;
for j in 0..=n {
for k in 0..=min_profit {
dp[i][j][k] = dp[i-1][j][k];
if j >= g {
let new_profit = std::cmp::min(min_profit, k + p);
dp[i][j][new_profit] = (dp[i][j][new_profit] + dp[i-1][j-g][k]) % 1_000_000_007;
}
}
}
}
let mut res = 0;
for j in 0..=n { res = (res + dp[len][j][min_profit]) % 1_000_000_007; }
res
}
}
TypeScript
class Solution {
profitableSchemes(n: number, minProfit: number, group: number[], profit: number[]): number {
const MOD = 1e9+7, len = group.length;
const dp: number[][][] = Array.from({length: len+1}, () => Array.from({length: n+1}, () => Array(minProfit+1).fill(0)));
dp[0][0][0] = 1;
for (let i = 1; i <= len; ++i) {
const g = group[i-1], p = profit[i-1];
for (let j = 0; j <= n; ++j) {
for (let k = 0; k <= minProfit; ++k) {
dp[i][j][k] = dp[i-1][j][k];
if (j >= g) {
const newProfit = Math.min(minProfit, k + p);
dp[i][j][newProfit] = (dp[i][j][newProfit] + dp[i-1][j-g][k]) % MOD;
}
}
}
}
let res = 0;
for (let j = 0; j <= n; ++j) res = (res + dp[len][j][minProfit]) % MOD;
return res;
}
}
Complexity
- ⏰ Time complexity:
O(len * n * minProfit)- For each crime, we update a DP table of size n x minProfit, resulting in O(len * n * minProfit) operations.
- 🧺 Space complexity:
O(len * n * minProfit)- The DP table stores the number of ways for each combination of crimes, members, and profit.