JAVA程序设计:盈利计划(LeetCode:879)

帮派里有 G 名成员,他们可能犯下各种各样的罪行。

第 i 种犯罪会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。

让我们把这些犯罪的任何子集称为盈利计划,该计划至少产生 P 的利润。

有多少种方案可以选择?因为答案很大,所以返回它模 10^9 + 7 的值。

示例 1:

输入:G = 5, P = 3, group = [2,2], profit = [2,3]
输出:2
解释: 
至少产生 3 的利润,该帮派可以犯下罪 0 和罪 1 ,或仅犯下罪 1 。
总的来说,有两种方案。
示例 2:

输入:G = 10, P = 5, group = [2,3,5], profit = [6,7,8]
输出:7
解释:
至少产生 5 的利润,只要他们犯其中一种罪就行,所以该帮派可以犯下任何罪行 。
有 7 种可能的计划:(0),(1),(2),(0,1),(0,2),(1,2),以及 (0,1,2) 。
 

提示:

1 <= G <= 100
0 <= P <= 100
1 <= group[i] <= 100
0 <= profit[i] <= 100
1 <= group.length = profit.length <= 100

思路:定义dp[i][j][k]表示前i个犯罪方案用了k个人获得利润为j的方案数。由于人数大于G,利润大于P都没有意义,因此我们将所用人数上限设为G,当利润大于P时一律看做P。

class Solution {
	
	private int mod=1000000007;
	
    public int profitableSchemes(int G, int P, int[] group, int[] profit) {
    	
    	int n=group.length;
    	long[][][] dp=new long[n+1][P+1][G+1];
    	
    	dp[0][0][0]=1;
    	
    	for(int i=1;i<=n;i++) {	
    		int num=group[i-1];
    		int val=profit[i-1];
    		
    		for(int j=0;j<=P;j++)
    			for(int k=0;k<=G;k++)
    				dp[i][j][k]=dp[i-1][j][k];
    		
    		for(int j=0;j<=P;j++) {
    			int nowVal=Math.min(val+j, P);
    			for(int k=0;k<=G-num;k++) {
    				int nowNum=num+k;
    				dp[i][nowVal][nowNum]+=dp[i-1][j][k];
    				dp[i][nowVal][nowNum]%=mod;
    			}
    		}
    	}
    	
    	long ans=0;
    	for(int i=0;i<=G;i++)
    		ans=(ans+dp[n][P][i])%mod;
    	
    	return (int)ans;
    }
}
原创文章 1111 获赞 194 访问量 25万+

猜你喜欢

转载自blog.csdn.net/haut_ykc/article/details/105853852
今日推荐