题目链接
分析
对每一个栈求前缀和 $sum[]$,即可将其转化为分组背包问题(将每个栈中取前 $1,2,3,\cdots, n$ 个分别看作一个物品,体积分别为 $1,2,3,\cdots, n$,价值为 $sum[1], sum[2], sum[3], \cdots, sum[n]$
令 $dp[i][j]$ 为从前 $i$ 个栈取 $j$ 个硬币时能取的最大金额,当前选择的物品由 $w$ 个金币构成,价值为 $v$
那么状态转移方程就是 $dp[i][j]=\max(dp[i-1][j], dp[i - 1][j - w] + v)$
在实现时反向进行遍历,可以去掉上述转移方程的第一维
代码实现
class Solution {
public:
int maxValueOfCoins(vector<vector<int>>& piles, int k) {
vector<int> dp(k + 1, 0);
for (auto& p : piles) {
int n = p.size();
partial_sum(p.begin(), p.end(), p.begin());
for(int i = k; i; --i) {
for(int j = 0; j < min(n, i); ++j) {
dp[i] = max(dp[i], dp[i - j - 1] + p[j]);
}
}
}
return dp[k];
}
};
复杂度分析
- 时间复杂度:$O(Nk)$,$N$ 为所有栈的长度之和
- 空间复杂度:$O(k)$