【动态规划-分组背包】【hard】力扣2218. 从栈中取出 K 个硬币的最大面值和

一张桌子上总共有 n 个硬币 栈 。每个栈有 正整数 个带面值的硬币。

每一次操作中,你可以从任意一个栈的 顶部 取出 1 个硬币,从栈中移除它,并放入你的钱包里。

给你一个列表 piles ,其中 piles[i] 是一个整数数组,分别表示第 i 个栈里 从顶到底 的硬币面值。同时给你一个正整数 k ,请你返回在 恰好 进行 k 次操作的前提下,你钱包里硬币面值之和 最大为多少 。

示例 1:
在这里插入图片描述
输入:piles = [[1,100,3],[7,8,9]], k = 2
输出:101
解释:
上图展示了几种选择 k 个硬币的不同方法。
我们可以得到的最大面值为 101 。

示例 2:
输入:piles = [[100],[100],[100],[100],[100],[100],[1,1,1,1,1,1,700]], k = 7
输出:706
解释:
如果我们所有硬币都从最后一个栈中取,可以得到最大面值和。
在这里插入图片描述
动态规划

class Solution {
public:
    int maxValueOfCoins(vector<vector<int>>& piles, int k) {
        vector<int> f(k+1);
        int num_n = 0;
        for(auto& pile : piles){
            int n = pile.size();
            for(int i = 1; i < n; i++){
                pile[i] += pile[i-1];
            }
            
            int num_n = min(num_n+n, k);
            for(int j = num_n; j > 0; j--){
                for(int w = 0; w < min(n,j); w++){
                    f[j] = max(f[j],f[j-w-1] + pile[w]); 
                }
            }
        }
        return f[k];
    }
};

时间复杂度:O(ks)。将外层循环与最内层循环合并,即每个栈的大小之和,记作 s,算上中间这层的循环,时间复杂度为 O(ks)。
空间复杂度:O(k)。

首先定义一个动态数组f,f[j]的含义是:当使用j个硬币所能达到的最大面值和。
我们遍历每一个栈的硬币,然后计算出前缀和,使pile[i]的含义变为前i+1个硬币的面值和。
然后定义一个整型num_n,他是用来判断j要从哪里开始向下循环,每当遍历一个栈的时候,num_n就会加上这个栈的硬币数n,然后保证不会超过k。

然后j就从num_n开始向下循环到j>0,然后第三重循环w的含义是目前遍历的栈选取w+1个硬币,然后这时候更新f[j],他会比较如果选取了这个栈的前w+1个硬币,那么有没有可能会出现比之前更大的情况。

最后f[k]的含义就是取出k个硬币时候的最大面值和,返回即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值