码迷,mamicode.com
首页 > 其他好文 > 详细

力扣 每日一题 879 盈利计划

时间:2021-06-10 18:05:22      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:思路   ddl   ash   pat   public   table   应该   情况   就是   

今天是个困难题。

集团里有 n 名员工,他们可以完成各种各样的工作创造利润。

第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。

工作的任何至少产生 minProfit 利润的子集称为 盈利计划 。并且工作的成员总数最多为 n 。

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

示例

输入:n = 5, minProfit = 3, group = [2,2], profit = [2,3]
输出:2
解释:至少产生 3 的利润,该集团可以完成工作 0 和工作 1 ,或仅完成工作 1 。
总的来说,有两种计划

 

从示例来看,不难看出题目的意思,最直接的思路就是每项工作都可以选,或者不选。如果选择做这个工作,则在扣除该工作的人数和盈利之后,看是否满足要求,如满足要求,结果加1。如果不选择这个工作,则继续往下遍历,最先想到的解决方案是深度优先算法,一般深度优先算法都会超时,但是为了验证思路对不对,先写一个出来看看效果。

 1 public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
 2         
 3         Set<List<Integer>> valueSet= new HashSet<>();
 4         dfs(n,minProfit,group,profit,0,valueSet);
 5         return valueSet.size();
 6     }
 7     LinkedList<Integer> path = new LinkedList<>();
 8     private void dfs(int n, int minProfit, int[] group, int[] profit, int currIdx,Set<List<Integer>> valueSet){
 9         if(n<0||(n==0&&minProfit>0)){
10             return;
11         }
12         if(minProfit<=0){
13            valueSet.add(new ArrayList<>(path));
14         }
15         for(int i = currIdx;i<group.length;i++){
16             path.addLast(i);
17             dfs(n-group[i],minProfit-profit[i],group,profit,i+1,valueSet);
18             path.removeLast();
19             dfs(n,minProfit,group,profit,i+1,valueSet);
20 
21         }
22 
23     }

因为遍历的时候有些结果集会重复计算,所以使用Set来过滤一下,也没有考虑到题目要求结果需要模1e9+7。将题目中的示例输入,结果是对的,起码方向对了,提交超时。

其实这种题目,求最值(最多,最少)的大部分都可以用动态规划来做,所以我们考虑动态规划。

根据以上深度优先算法的参数可知,动态规划涉及的维度有3个,n,group.length,minprofit,所以首先可以开一个三维数组。

int[][][] dp = new int[group.length+1][n+1][[minprofit+1]

然后我们来思考一下数据之间的关联,工作只有两种选择,选与不选,如果不选择,当前的值应该等于之前的值,即:

dp[i][j][k]=dp[i-1][j][k]

如果选择,则当前的值应为之前的值在人数和盈利减去当前项的值,即:

dp[i][j][k]=dp[i-1][j-group[i]][k-profit[i]]

最终的值为两者相加,即:

dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-group[i]][k-profit[i]]

接下来,需要注意的是:

1.如果选择该项工作,需保证j>group[i],否认只能不选

2.k-profit[i]有可能为负值,一般解决负值的方法就是开双倍的空间来存储,以模拟存储负值的情况,这里不需要,因为盈利为负值可以都计算在满足条件,即profit为0的情况。

基于上述分析,最终的版本。

 public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
        int mod = (int) 1e9+7;
        int m = group.length;
        int[][][] dp = new int[m+1][n+1][minProfit+1];
        for(int i = 0;i<n+1;i++){
            dp[0][i][0]=1;
        }
        for(int i =1;i<=m;i++){
            int gs=  group[i-1];
            int ps = 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>=gs){
                        dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-gs][Math.max(k-ps,0)])%mod;
                    }
                }
            }
        }
        return dp[m][n][minProfit];
    }

 

力扣 每日一题 879 盈利计划

标签:思路   ddl   ash   pat   public   table   应该   情况   就是   

原文地址:https://www.cnblogs.com/jejas/p/14869351.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!