https://leetcode.com/problems/profitable-schemes/
题意:有G个人,有n种犯罪方式每种犯罪方式都可以获得profit[i]的利益,每种犯罪方式都需要group[i]个人,要使获得利益大于等于P,求有多少种方式。
思路:G个人等价于背包的容量限制。设dp[i][j][k]表示前i种犯罪方式,使用j个人,获得k的利益的方案数。由于第i种犯罪方式只和第i-1种有关,所以可以滚动成2维dp,dp[j][k]即可,不过需要注意的是j,k需要逆推。
dp[j][k]+=dp[j-group[i]] [k-profit[i]];
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
class Solution {
public:
int profitableSchemes(int G, int P, vector<int>& group, vector<int>& profit) {
int dp[105][10005];
memset(dp,0,sizeof(dp));
int n = profit.size();
int mod = 1e9+7;
int tot=0;
for(auto &t:profit){
tot+=t;
}
dp[0][0]=1;
for(int i=0;i<n;i++){
for(int j=G;j>=group[i];j--){
for(int k=tot;k>=profit[i];k--){
dp[j][k]+=dp[j-group[i]][k-profit[i]];
dp[j][k]%=mod;
}
}
}
int ans=0;
for(int k=P;k<=tot;k++){
for(int i=1;i<=G;i++){
ans=(ans+dp[i][k])%mod;
}
}
return ans;
}
};