@@ -66,15 +66,21 @@ tags:
6666
6767<!-- solution:start -->
6868
69- ### 方法一:动态规划
69+ ### 方法一:动态规划(分组背包)
7070
71- 对每个栈求前缀和 $s$,$s_i$ 视为一个体积为 $i$ 且价值为 $s_i$ 的物品 。
71+ 我们定义 $f [ i ] [ j ] $ 表示从前 $i$ 组中取出 $j$ 个硬币的最大面值和,那么答案为 $f [ n ] [ k ] $,其中 $n$ 为栈的数量 。
7272
73- 问题转化为求从 $n$ 个物品组中取物品体积为 $k$,且每组最多取一个物品时的最大价值和 。
73+ 对于第 $i$ 组,我们可以选择取前 $0$, $1$, $2$, $\cdots$, $k$ 个硬币。我们可以通过前缀和数组 $s$ 来快速计算出取前 $h$ 个硬币的面值和 。
7474
75- 定义 $dp [ i ] [ j ] $ 表示从前 $i$ 个组中取体积之和为 $j$ 的物品时的最大价值和。
75+ 状态转移方程为:
7676
77- 枚举第 $i$ 组所有物品,设当前物品体积为 $w$,价值为 $v$,则有 $f[ i] [ j ] =max(f[ i] [ j ] ,f[ i-1] [ j-w ] +v)$。
77+ $$
78+ f[i][j] = \max(f[i][j], f[i - 1][j - h] + s[h])
79+ $$
80+
81+ 其中 $0 \leq h \leq j$,而 $s[ h] $ 表示第 $i$ 组中取前 $h$ 个硬币的面值和。
82+
83+ 时间复杂度 $O(k \times L)$,空间复杂度 $O(n \times k)$。其中 $L$ 为所有硬币的数量,而 $n$ 为栈的数量。
7884
7985<!-- tabs:start -->
8086
@@ -83,15 +89,16 @@ tags:
8389``` python
8490class Solution :
8591 def maxValueOfCoins (self , piles : List[List[int ]], k : int ) -> int :
86- presum = [list (accumulate(p, initial = 0 )) for p in piles]
8792 n = len (piles)
88- dp = [[0 ] * (k + 1 ) for _ in range (n + 1 )]
89- for i, s in enumerate (presum, 1 ):
93+ f = [[0 ] * (k + 1 ) for _ in range (n + 1 )]
94+ for i, nums in enumerate (piles, 1 ):
95+ s = list (accumulate(nums, initial = 0 ))
9096 for j in range (k + 1 ):
91- for idx, v in enumerate (s):
92- if j >= idx:
93- dp[i][j] = max (dp[i][j], dp[i - 1 ][j - idx] + v)
94- return dp[- 1 ][- 1 ]
97+ for h, w in enumerate (s):
98+ if j < h:
99+ break
100+ f[i][j] = max (f[i][j], f[i - 1 ][j - h] + w)
101+ return f[n][k]
95102```
96103
97104#### Java
@@ -100,26 +107,21 @@ class Solution:
100107class Solution {
101108 public int maxValueOfCoins (List<List<Integer > > piles , int k ) {
102109 int n = piles. size();
103- List<int[]> presum = new ArrayList<> ();
104- for (List<Integer > p : piles) {
105- int m = p. size();
106- int [] s = new int [m + 1 ];
107- for (int i = 0 ; i < m; ++ i) {
108- s[i + 1 ] = s[i] + p. get(i);
110+ int [][] f = new int [n + 1 ][k + 1 ];
111+ for (int i = 1 ; i <= n; i++ ) {
112+ List<Integer > nums = piles. get(i - 1 );
113+ int [] s = new int [nums. size() + 1 ];
114+ s[0 ] = 0 ;
115+ for (int j = 1 ; j <= nums. size(); j++ ) {
116+ s[j] = s[j - 1 ] + nums. get(j - 1 );
109117 }
110- presum. add(s);
111- }
112- int [] dp = new int [k + 1 ];
113- for (int [] s : presum) {
114- for (int j = k; j >= 0 ; -- j) {
115- for (int idx = 0 ; idx < s. length; ++ idx) {
116- if (j >= idx) {
117- dp[j] = Math . max(dp[j], dp[j - idx] + s[idx]);
118- }
118+ for (int j = 0 ; j <= k; j++ ) {
119+ for (int h = 0 ; h < s. length && h <= j; h++ ) {
120+ f[i][j] = Math . max(f[i][j], f[i - 1 ][j - h] + s[h]);
119121 }
120122 }
121123 }
122- return dp [k];
124+ return f[n] [k];
123125 }
124126}
125127```
@@ -130,22 +132,21 @@ class Solution {
130132class Solution {
131133public:
132134 int maxValueOfCoins(vector<vector<int >>& piles, int k) {
133- vector<vector<int >> presum;
134- for (auto& p : piles) {
135- int m = p.size();
136- vector<int > s(m + 1);
137- for (int i = 0; i < m; ++i) s[ i + 1] = s[ i] + p[ i] ;
138- presum.push_back(s);
139- }
140- vector<int > dp(k + 1);
141- for (auto& s : presum) {
142- for (int j = k; ~ j; --j) {
143- for (int idx = 0; idx < s.size(); ++idx) {
144- if (j >= idx) dp[ j] = max(dp[ j] , dp[ j - idx] + s[ idx] );
135+ int n = piles.size();
136+ vector<vector<int >> f(n + 1, vector<int >(k + 1));
137+ for (int i = 1; i <= n; i++) {
138+ vector<int > nums = piles[ i - 1] ;
139+ vector<int > s(nums.size() + 1);
140+ for (int j = 1; j <= nums.size(); j++) {
141+ s[ j] = s[ j - 1] + nums[ j - 1] ;
142+ }
143+ for (int j = 0; j <= k; j++) {
144+ for (int h = 0; h < s.size() && h <= j; h++) {
145+ f[ i] [ j ] = max(f[ i] [ j ] , f[ i - 1] [ j - h ] + s[ h] );
145146 }
146147 }
147148 }
148- return dp [ k] ;
149+ return f [ n ] [ k ] ;
149150 }
150151};
151152```
@@ -154,26 +155,50 @@ public:
154155
155156```go
156157func maxValueOfCoins(piles [][]int, k int) int {
157- var presum [][]int
158- for _, p := range piles {
159- m := len(p)
160- s := make([]int, m+1)
161- for i, v := range p {
162- s[i+1] = s[i] + v
163- }
164- presum = append(presum, s)
158+ n := len(piles)
159+ f := make([][]int, n+1)
160+ for i := range f {
161+ f[i] = make([]int, k+1)
165162 }
166- dp := make([]int, k+1)
167- for _, s := range presum {
168- for j := k; j >= 0; j-- {
169- for idx, v := range s {
170- if j >= idx {
171- dp[j] = max(dp[j], dp[j-idx]+v)
163+ for i := 1; i <= n; i++ {
164+ nums := piles[i-1]
165+ s := make([]int, len(nums)+1)
166+ for j := 1; j <= len(nums); j++ {
167+ s[j] = s[j-1] + nums[j-1]
168+ }
169+
170+ for j := 0; j <= k; j++ {
171+ for h, w := range s {
172+ if j < h {
173+ break
172174 }
175+ f[i][j] = max(f[i][j], f[i-1][j-h]+w)
173176 }
174177 }
175178 }
176- return dp[k]
179+ return f[n][k]
180+ }
181+ ```
182+
183+ #### TypeScript
184+
185+ ``` ts
186+ function maxValueOfCoins(piles : number [][], k : number ): number {
187+ const n = piles .length ;
188+ const f: number [][] = Array .from ({ length: n + 1 }, () => Array (k + 1 ).fill (0 ));
189+ for (let i = 1 ; i <= n ; i ++ ) {
190+ const nums = piles [i - 1 ];
191+ const s = Array (nums .length + 1 ).fill (0 );
192+ for (let j = 1 ; j <= nums .length ; j ++ ) {
193+ s [j ] = s [j - 1 ] + nums [j - 1 ];
194+ }
195+ for (let j = 0 ; j <= k ; j ++ ) {
196+ for (let h = 0 ; h < s .length && h <= j ; h ++ ) {
197+ f [i ][j ] = Math .max (f [i ][j ], f [i - 1 ][j - h ] + s [h ]);
198+ }
199+ }
200+ }
201+ return f [n ][k ];
177202}
178203```
179204
@@ -192,14 +217,100 @@ func maxValueOfCoins(piles [][]int, k int) int {
192217``` python
193218class Solution :
194219 def maxValueOfCoins (self , piles : List[List[int ]], k : int ) -> int :
195- presum = [list (accumulate(p, initial = 0 )) for p in piles]
196- dp = [ 0 ] * (k + 1 )
197- for s in presum:
220+ f = [0 ] * (k + 1 )
221+ for nums in piles:
222+ s = list (accumulate(nums, initial = 0 ))
198223 for j in range (k, - 1 , - 1 ):
199- for idx, v in enumerate (s):
200- if j >= idx:
201- dp[j] = max (dp[j], dp[j - idx] + v)
202- return dp[- 1 ]
224+ for h, w in enumerate (s):
225+ if j < h:
226+ break
227+ f[j] = max (f[j], f[j - h] + w)
228+ return f[k]
229+ ```
230+
231+ #### Java
232+
233+ ``` java
234+ class Solution {
235+ public int maxValueOfCoins (List<List<Integer > > piles , int k ) {
236+ int [] f = new int [k + 1 ];
237+ for (var nums : piles) {
238+ int [] s = new int [nums. size() + 1 ];
239+ for (int j = 1 ; j <= nums. size(); ++ j) {
240+ s[j] = s[j - 1 ] + nums. get(j - 1 );
241+ }
242+ for (int j = k; j >= 0 ; -- j) {
243+ for (int h = 0 ; h < s. length && h <= j; ++ h) {
244+ f[j] = Math . max(f[j], f[j - h] + s[h]);
245+ }
246+ }
247+ }
248+ return f[k];
249+ }
250+ }
251+ ```
252+
253+ #### C++
254+
255+ ``` cpp
256+ class Solution {
257+ public:
258+ int maxValueOfCoins(vector<vector<int >>& piles, int k) {
259+ vector<int > f(k + 1);
260+ for (auto& nums : piles) {
261+ vector<int > s(nums.size() + 1);
262+ for (int j = 1; j <= nums.size(); ++j) {
263+ s[ j] = s[ j - 1] + nums[ j - 1] ;
264+ }
265+ for (int j = k; j >= 0; --j) {
266+ for (int h = 0; h < s.size() && h <= j; ++h) {
267+ f[ j] = max(f[ j] , f[ j - h] + s[ h] );
268+ }
269+ }
270+ }
271+ return f[ k] ;
272+ }
273+ };
274+ ```
275+
276+ #### Go
277+
278+ ```go
279+ func maxValueOfCoins(piles [][]int, k int) int {
280+ f := make([]int, k+1)
281+ for _, nums := range piles {
282+ s := make([]int, len(nums)+1)
283+ for j := 1; j <= len(nums); j++ {
284+ s[j] = s[j-1] + nums[j-1]
285+ }
286+ for j := k; j >= 0; j-- {
287+ for h := 0; h < len(s) && h <= j; h++ {
288+ f[j] = max(f[j], f[j-h]+s[h])
289+ }
290+ }
291+ }
292+ return f[k]
293+ }
294+ ```
295+
296+ #### TypeScript
297+
298+ ``` ts
299+ function maxValueOfCoins(piles : number [][], k : number ): number {
300+ const f: number [] = Array (k + 1 ).fill (0 );
301+ for (const nums of piles ) {
302+ const s: number [] = Array (nums .length + 1 ).fill (0 );
303+ for (let j = 1 ; j <= nums .length ; j ++ ) {
304+ s [j ] = s [j - 1 ] + nums [j - 1 ];
305+ }
306+ for (let j = k ; j >= 0 ; j -- ) {
307+ for (let h = 0 ; h < s .length && h <= j ; h ++ ) {
308+ f [j ] = Math .max (f [j ], f [j - h ] + s [h ]);
309+ }
310+ }
311+ }
312+ return f [k ];
313+ }
203314```
204315
205316<!-- tabs: end -->
0 commit comments