# 0879. Profitable Schemes
###### tags: `Leetcode` `Hard` `Dynamic Programming` `Knapsack Problem`
Link: https://leetcode.com/problems/profitable-schemes/
## 思路
典型背包问题
但区别在于这里有两个限制条件: profit最少是```minProfit```, 人数要最多是```n```
所以其实是一个3D的背包问题 但是可以压缩成2D
如果按照之前的方法就需要先算出total profit和total people 然后两层回圈遍历```[0:total profit][0:total people]```
但其实仔细观察可以发现我们可以在遍历过程中把大于```minProfit```的方法数全都归在```minProfit```里面 把人数大于```n```的方法直接抛弃掉(之所以这样做是因为在遍历过程中minProfit和people数一定不会减少)
## Code
java
```java=
class Solution {
public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
int totalp = 0;
int l = group.length;
int mod = 1000000007;
for(int i=0; i<l; i++) totalp += group[i];
long[][] dp = new long[n+1][minProfit+1];
dp[0][0] = 1;
for(int i=0; i<l; i++){
for(int j=n-group[i]; j>=0; j--){
for(int k=minProfit; k>=0; k--){
dp[j+group[i]][Math.min(minProfit, k+profit[i])]+=dp[j][k];
dp[j+group[i]][Math.min(minProfit, k+profit[i])] %= mod;
}
}
}
long ans = 0;
for(int i=0; i<=n; i++){
ans = (ans+dp[i][minProfit])%mod;
}
return (int)ans;
}
}
```
c++
```cpp=
class Solution {
public:
int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
int l = group.size();
int mod = 1000000007;
auto dp = vector<vector<long>>(n+1, vector<long>(minProfit+1));
dp[0][0] = 1;
for(int i=1; i<=l; i++){
int num = group[i-1];
for(int j=n-num; j>=0; j--){
for(int k=0; k<=minProfit; k++){
dp[j+num][min(k+profit[i-1], minProfit)] += dp[j][k];
dp[j+num][min(k+profit[i-1], minProfit)] %= mod;
}
}
}
long ans = 0;
for(int i=0; i<=n; i++) ans = (ans+dp[i][minProfit])%mod;
return (int)ans;
}
};
```
```