@@ -96,32 +96,251 @@ tags:
96
96
97
97
<!-- solution:start -->
98
98
99
- ### 方法一
99
+ ### 方法一:动态规划
100
+
101
+ 根据题目描述,从 $(0, 0)$ 出发的小朋友要想在 $n - 1$ 步后到达 $(n - 1, n - 1)$,那么他只能走主对角线上的房间 $(i, i)$,即 $i = 0, 1, \ldots, n - 1$。而从 $(0, n - 1)$ 出发的小朋友只能走主对角线以上的房间,而从 $(n - 1, 0)$ 出发的小朋友只能走主对角线以下的房间。这意味着三个小朋友除了在 $(n - 1, n - 1)$ 到达终点外,其他房间都不会有多个小朋友重复进入。
102
+
103
+ 我们可以用动态规划的方式,计算从 $(0, n - 1)$ 和 $(n - 1, 0)$ 出发的小朋友达到 $(i, j)$ 时,能收集到的水果数。定义 $f[ i] [ j ] $ 表示小朋友到达 $(i, j)$ 时能收集到的水果数。
104
+
105
+ 对于从 $(0, n - 1)$ 出发的小朋友,状态转移方程为:
106
+
107
+ $$
108
+ f[i][j] = \max(f[i - 1][j], f[i - 1][j - 1], f[i - 1][j + 1]) + \text{fruits}[i][j]
109
+ $$
110
+
111
+ 注意,只有当 $j + 1 < n$ 时,$f[ i - 1] [ j + 1 ] $ 才是有效的。
112
+
113
+ 对于从 $(n - 1, 0)$ 出发的小朋友,状态转移方程为:
114
+
115
+ $$
116
+ f[i][j] = \max(f[i][j - 1], f[i - 1][j - 1], f[i + 1][j - 1]) + \text{fruits}[i][j]
117
+ $$
118
+
119
+ 同样,只有当 $i + 1 < n$ 时,$f[ i + 1] [ j - 1 ] $ 才是有效的。
120
+
121
+ 最后,答案为 $\sum_ {i=0}^{n-1} \text{fruits}[ i] [ i ] + f[ n-2] [ n-1 ] + f[ n-1] [ n-2 ] $,即主对角线上的水果数加上两个小朋友到达 $(n - 2, n - 1)$ 和 $(n - 1, n - 2)$ 时能收集到的水果数。
122
+
123
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为房间的边长。
100
124
101
125
<!-- tabs:start -->
102
126
103
127
#### Python3
104
128
105
129
``` python
106
-
130
+ class Solution :
131
+ def maxCollectedFruits (self , fruits : List[List[int ]]) -> int :
132
+ n = len (fruits)
133
+ f = [[- inf] * n for _ in range (n)]
134
+ f[0 ][n - 1 ] = fruits[0 ][n - 1 ]
135
+ for i in range (1 , n):
136
+ for j in range (i + 1 , n):
137
+ f[i][j] = max (f[i - 1 ][j], f[i - 1 ][j - 1 ]) + fruits[i][j]
138
+ if j + 1 < n:
139
+ f[i][j] = max (f[i][j], f[i - 1 ][j + 1 ] + fruits[i][j])
140
+ f[n - 1 ][0 ] = fruits[n - 1 ][0 ]
141
+ for j in range (1 , n):
142
+ for i in range (j + 1 , n):
143
+ f[i][j] = max (f[i][j - 1 ], f[i - 1 ][j - 1 ]) + fruits[i][j]
144
+ if i + 1 < n:
145
+ f[i][j] = max (f[i][j], f[i + 1 ][j - 1 ] + fruits[i][j])
146
+ return sum (fruits[i][i] for i in range (n)) + f[n - 2 ][n - 1 ] + f[n - 1 ][n - 2 ]
107
147
```
108
148
109
149
#### Java
110
150
111
151
``` java
112
-
152
+ class Solution {
153
+ public int maxCollectedFruits (int [][] fruits ) {
154
+ int n = fruits. length;
155
+ final int inf = 1 << 29 ;
156
+ int [][] f = new int [n][n];
157
+ for (var row : f) {
158
+ Arrays . fill(row, - inf);
159
+ }
160
+ f[0 ][n - 1 ] = fruits[0 ][n - 1 ];
161
+ for (int i = 1 ; i < n; i++ ) {
162
+ for (int j = i + 1 ; j < n; j++ ) {
163
+ f[i][j] = Math . max(f[i - 1 ][j], f[i - 1 ][j - 1 ]) + fruits[i][j];
164
+ if (j + 1 < n) {
165
+ f[i][j] = Math . max(f[i][j], f[i - 1 ][j + 1 ] + fruits[i][j]);
166
+ }
167
+ }
168
+ }
169
+ f[n - 1 ][0 ] = fruits[n - 1 ][0 ];
170
+ for (int j = 1 ; j < n; j++ ) {
171
+ for (int i = j + 1 ; i < n; i++ ) {
172
+ f[i][j] = Math . max(f[i][j - 1 ], f[i - 1 ][j - 1 ]) + fruits[i][j];
173
+ if (i + 1 < n) {
174
+ f[i][j] = Math . max(f[i][j], f[i + 1 ][j - 1 ] + fruits[i][j]);
175
+ }
176
+ }
177
+ }
178
+ int ans = f[n - 2 ][n - 1 ] + f[n - 1 ][n - 2 ];
179
+ for (int i = 0 ; i < n; i++ ) {
180
+ ans += fruits[i][i];
181
+ }
182
+ return ans;
183
+ }
184
+ }
113
185
```
114
186
115
187
#### C++
116
188
117
189
``` cpp
118
-
190
+ class Solution {
191
+ public:
192
+ int maxCollectedFruits(vector<vector<int >>& fruits) {
193
+ int n = fruits.size();
194
+ const int inf = 1 << 29;
195
+ vector<vector<int >> f(n, vector<int >(n, -inf));
196
+
197
+ f[0][n - 1] = fruits[0][n - 1];
198
+ for (int i = 1; i < n; i++) {
199
+ for (int j = i + 1; j < n; j++) {
200
+ f[i][j] = max(f[i - 1][j], f[i - 1][j - 1]) + fruits[i][j];
201
+ if (j + 1 < n) {
202
+ f[i][j] = max(f[i][j], f[i - 1][j + 1] + fruits[i][j]);
203
+ }
204
+ }
205
+ }
206
+
207
+ f[n - 1 ][0 ] = fruits[n - 1 ][0 ];
208
+ for (int j = 1 ; j < n; j++) {
209
+ for (int i = j + 1; i < n; i++) {
210
+ f[i][j] = max(f[i][j - 1], f[i - 1][j - 1]) + fruits[i][j];
211
+ if (i + 1 < n) {
212
+ f[i][j] = max(f[i][j], f[i + 1][j - 1] + fruits[i][j]);
213
+ }
214
+ }
215
+ }
216
+
217
+ int ans = f[n - 2][n - 1] + f[n - 1][n - 2];
218
+ for (int i = 0; i < n; i++) {
219
+ ans += fruits[i][i];
220
+ }
221
+
222
+ return ans;
223
+ }
224
+ };
119
225
```
120
226
121
227
#### Go
122
228
123
229
``` go
230
+ func maxCollectedFruits (fruits [][]int ) int {
231
+ n := len (fruits)
232
+ const inf = 1 << 29
233
+ f := make ([][]int , n)
234
+ for i := range f {
235
+ f[i] = make ([]int , n)
236
+ for j := range f[i] {
237
+ f[i][j] = -inf
238
+ }
239
+ }
240
+
241
+ f[0 ][n-1 ] = fruits[0 ][n-1 ]
242
+ for i := 1 ; i < n; i++ {
243
+ for j := i + 1 ; j < n; j++ {
244
+ f[i][j] = max (f[i-1 ][j], f[i-1 ][j-1 ]) + fruits[i][j]
245
+ if j+1 < n {
246
+ f[i][j] = max (f[i][j], f[i-1 ][j+1 ]+fruits[i][j])
247
+ }
248
+ }
249
+ }
250
+
251
+ f[n-1 ][0 ] = fruits[n-1 ][0 ]
252
+ for j := 1 ; j < n; j++ {
253
+ for i := j + 1 ; i < n; i++ {
254
+ f[i][j] = max (f[i][j-1 ], f[i-1 ][j-1 ]) + fruits[i][j]
255
+ if i+1 < n {
256
+ f[i][j] = max (f[i][j], f[i+1 ][j-1 ]+fruits[i][j])
257
+ }
258
+ }
259
+ }
260
+
261
+ ans := f[n-2 ][n-1 ] + f[n-1 ][n-2 ]
262
+ for i := 0 ; i < n; i++ {
263
+ ans += fruits[i][i]
264
+ }
265
+
266
+ return ans
267
+ }
268
+ ```
269
+
270
+ #### TypeScript
271
+
272
+ ``` ts
273
+ function maxCollectedFruits(fruits : number [][]): number {
274
+ const n = fruits .length ;
275
+ const inf = 1 << 29 ;
276
+ const f: number [][] = Array .from ({ length: n }, () => Array (n ).fill (- inf ));
277
+
278
+ f [0 ][n - 1 ] = fruits [0 ][n - 1 ];
279
+ for (let i = 1 ; i < n ; i ++ ) {
280
+ for (let j = i + 1 ; j < n ; j ++ ) {
281
+ f [i ][j ] = Math .max (f [i - 1 ][j ], f [i - 1 ][j - 1 ]) + fruits [i ][j ];
282
+ if (j + 1 < n ) {
283
+ f [i ][j ] = Math .max (f [i ][j ], f [i - 1 ][j + 1 ] + fruits [i ][j ]);
284
+ }
285
+ }
286
+ }
287
+
288
+ f [n - 1 ][0 ] = fruits [n - 1 ][0 ];
289
+ for (let j = 1 ; j < n ; j ++ ) {
290
+ for (let i = j + 1 ; i < n ; i ++ ) {
291
+ f [i ][j ] = Math .max (f [i ][j - 1 ], f [i - 1 ][j - 1 ]) + fruits [i ][j ];
292
+ if (i + 1 < n ) {
293
+ f [i ][j ] = Math .max (f [i ][j ], f [i + 1 ][j - 1 ] + fruits [i ][j ]);
294
+ }
295
+ }
296
+ }
297
+
298
+ let ans = f [n - 2 ][n - 1 ] + f [n - 1 ][n - 2 ];
299
+ for (let i = 0 ; i < n ; i ++ ) {
300
+ ans += fruits [i ][i ];
301
+ }
302
+
303
+ return ans ;
304
+ }
305
+ ```
124
306
307
+ #### Rust
308
+
309
+ ``` rust
310
+ impl Solution {
311
+ pub fn max_collected_fruits (fruits : Vec <Vec <i32 >>) -> i32 {
312
+ let n = fruits . len ();
313
+ let inf = 1 << 29 ;
314
+ let mut f = vec! [vec! [- inf ; n ]; n ];
315
+
316
+ f [0 ][n - 1 ] = fruits [0 ][n - 1 ];
317
+ for i in 1 .. n {
318
+ for j in i + 1 .. n {
319
+ f [i ][j ] = std :: cmp :: max (f [i - 1 ][j ], f [i - 1 ][j - 1 ]) + fruits [i ][j ];
320
+ if j + 1 < n {
321
+ f [i ][j ] = std :: cmp :: max (f [i ][j ], f [i - 1 ][j + 1 ] + fruits [i ][j ]);
322
+ }
323
+ }
324
+ }
325
+
326
+ f [n - 1 ][0 ] = fruits [n - 1 ][0 ];
327
+ for j in 1 .. n {
328
+ for i in j + 1 .. n {
329
+ f [i ][j ] = std :: cmp :: max (f [i ][j - 1 ], f [i - 1 ][j - 1 ]) + fruits [i ][j ];
330
+ if i + 1 < n {
331
+ f [i ][j ] = std :: cmp :: max (f [i ][j ], f [i + 1 ][j - 1 ] + fruits [i ][j ]);
332
+ }
333
+ }
334
+ }
335
+
336
+ let mut ans = f [n - 2 ][n - 1 ] + f [n - 1 ][n - 2 ];
337
+ for i in 0 .. n {
338
+ ans += fruits [i ][i ];
339
+ }
340
+
341
+ ans
342
+ }
343
+ }
125
344
```
126
345
127
346
<!-- tabs:end -->
0 commit comments