Profitable Schemes

Updated on 08 July, 2025
Profitable Schemes header image

Problem Statement

In this problem, we are provided with a group consisting of n members. Each member can participate in various crimes identified by two lists: group and profit. Each index i in the lists correlates thus:

  • group[i] specifies the number of members required to commit the i-th crime.
  • profit[i] indicates the profit made from the i-th crime.

A crime can only be done if the required members in group[i] have not participated in another crime. We define a profitable scheme as a combination of any crimes where the combined profit meets or exceeds a threshold minProfit while using no more than n members.

The challenge is to calculate the number of possible profitable schemes under these conditions. Due to potentially large results, the output must be given 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).

Constraints

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

Approach and Intuition

  1. We need to consider how to choose various combinations of crimes such that the conditions on membership and profit are both satisfied.

  2. To achieve this, recognize the problem structure which is similar to a knapsack problem where:

    • The total number of members (n) acts like the "weight capacity" of a knapsack.
    • The group list provides the "weight" of each item (crime).
    • The profit list provides the "value" of each item (crime's profit).
    • The task is to maximize the value (profit) while not exceeding the weight capacity (total members), ensuring that we meet a minimum value (minProfit).
  3. Dynamic programming (DP) can be effectively applied here:

    • Create a DP table where dp[j][k] stores the number of ways to achieve at least k profit using exactly j members.
    • Iterate through each crime, updating the DP table on how each crime impacts potential profits and membership usage.
  4. By iterating through crimes and updating the DP states for various member counts and profit levels, we can build upon smaller sub-problems to solve larger ones.

  5. The answer will be located in combining all possible membership usages (from 0 to n) that result in meeting the minimum profit requirement (minProfit).

Solutions

  • C++
cpp
class Solution {
public:
    int modulo = 1000000007;
    int memo[101][101][101];
              
    int maxProfitPlans(int n, int minProfit, vector<int>& group, vector<int>& profit) {
        // Set initial conditions
        for (int count = 0; count <= n; count++) {
            memo[group.size()][count][minProfit] = 1;
        }
            
        for (int i = group.size() - 1; i >= 0; i--) {
            for (int count = 0; count <= n; count++) {
                for(int profitSoFar = 0; profitSoFar <= minProfit; profitSoFar++) {
                    // Carry over previous scenarios without including the current group
                    memo[i][count][profitSoFar] = memo[i + 1][count][profitSoFar];
                    if (count + group[i] <= n) {
                        // Include current group's contribution
                        memo[i][count][profitSoFar] 
                            = (memo[i][count][profitSoFar] + memo[i + 1][count + group[i]][min(minProfit, profitSoFar + profit[i])]) % modulo;
                    }
                }
            }
        }
            
        return memo[0][0][0];
    }
};

The provided C++ code defines a solution to the "Profitable Schemes" problem using dynamic programming. The class Solution includes the method maxProfitPlans which computes the number of ways to achieve at least minProfit profit using up to n members from various groups, each potentially contributing a different amount of profit.

Key elements of the solution include:

  • An integer modulo set to 1000000007 to ensure results are returned modulo 10^9 + 7.
  • A 3D memoization array memo[101][101][101] used to store intermediate results.
  • Initialization of memoization values for base cases where the group size is zero but a certain profit needs to be achieved with a certain number of people.
  • Nested loops to iterate through every group member, every possible worker count up to n, and every possible profit amount up to minProfit.
  • Conditions to either skip including a group or to include it while adjusting the profit sum and member count accordingly.

The function finally returns the number of ways to achieve at least minProfit from no groups and no members.

Ensure to have vector<int> included in your packages, as this data structure is crucial for holding the group sizes and profit contributions. This solution provides an optimized approach to handle large inputs efficiently by utilizing memoization and iterative calculations, suitable for problems involving combinations and resource allocation under constraints.

  • Java
java
class SchemeCalculator {
    int modulus = 1000000007;
    int[][][] memo = new int[101][101][101];
    
    public int calculateSchemes(int G, int targetProfit, int[] teams, int[] earnings) {
        // Initialize dp for base cases
        for (int g = 0; g <= G; g++) {
            memo[teams.length][g][targetProfit] = 1;
        }
    
        for (int i = teams.length - 1; i >= 0; i--) {
            for (int g = 0; g <= G; g++) {
                for (int p = 0; p <= targetProfit; p++) {
                    // Calculate schemes without using current team
                    memo[i][g][p] = memo[i + 1][g][p];
                    if (g + teams[i] <= G) {
                        // Incorporate current team into the schemes
                        memo[i][g][p] = (memo[i][g][p] + memo[i + 1][g + teams[i]][Math.min(targetProfit, p + earnings[i])]) % modulus;
                    }
                }
            }
        }
    
        return memo[0][0][0];
    }
}

The Profitable Schemes problem consists of counting the number of ways to achieve a target profit using a designated number of groups, each having a certain number of members and potential profit. This solution is implemented in Java using a dynamic programming approach.

The approach involves utilizing a three-dimensional dynamic programming (DP) table memo, where:

  • The first dimension represents the team index.
  • The second dimension corresponds to the number of people involved.
  • The third dimension is used for the accumulated profit.

The solution initializes the base cases in the DP table where for all possible group sizes up to the limit G, if actions reach the target profit at the last job, they are considered viable, hence initialized to 1.

The core of the solution iteratively calculates the number of schemes:

  • For each backward iteration from the last available team to the first (teams.length - 1 to 0).
  • For each possible group size up to G.
  • For each profit level from 0 to targetProfit.

In each iteration:

  • The DP cell memo[i][g][p] is initially set to the value from the case where the current team is not chosen – memo[i + 1][g][p].
  • If the current team can be used without breaching the group size limit (g + teams[i] <= G), the DP value is updated to add schemes that include the profits from using the current team.

Values are computed modulo 1000000007 to manage large numbers.

The result, which is the count of different ways to achieve at most the target profit with the available teams and members limit, is stored in memo[0][0][0]. The return from calculateSchemes method gives this result, making this a comprehensive solution utilizing memoization to ensure efficiency by avoiding redundant calculations.

Comments

No comments yet.