62
62
63
63
### 方法一:动态规划
64
64
65
- 线性 DP。题目中 ,玩家从 ` (0, 0) ` 到 ` (N -1, N -1)` 后又重新返回到起始点 ` (0, 0) ` ,我们可以视为玩家两次从 ` (0, 0) ` 出发到 ` (N -1, N -1)` 。
65
+ 根据题目描述 ,玩家从 $ (0, 0)$ 出发,到达 $(n -1, n -1)$ 后,又重新返回到起始点 $ (0, 0)$ ,我们可以视为玩家两次从 $ (0, 0)$ 出发,到达 $(n -1, n -1)$ 。
66
66
67
- 定义 ` dp [k][i1][i2] ` 表示两次路径同时走了 k 步,并且第一次走到 ` (i1 , k-i1) ` ,第二次走到 ` (i2 , k-i2) ` 的所有路径中,可获得的樱桃数量的最大值 。
67
+ 因此,我们定义 $f [ k] [ i_1 ] [ i_2 ] $ 表示两次都走了 $k$ 步,分别到达 $(i_1 , k-i_1)$ 和 $(i_2 , k-i_2)$ 时,能够摘到的最多樱桃数。初始时 $f [ 0 ] [ 0 ] [ 0 ] = grid [ 0 ] [ 0 ] $。其余 $f [ k ] [ i_1 ] [ i_2 ] $ 的初始值为负无穷。答案为 $\max(0, f [ 2n-2 ] [ n-1 ] [ n-1 ] )$ 。
68
68
69
- 类似题型:方格取数、传纸条。
69
+ 我们可以根据题目描述,得到状态转移方程:
70
+
71
+ $$
72
+ f[k][i_1][i_2] = \max(f[k-1][x_1][x_2] + t, f[k][i_1][i_2])
73
+ $$
74
+
75
+ 其中 $t$ 表示 $(i_1, k-i_1)$ 和 $(i_2, k-i_2)$ 位置上的樱桃数,而 $x_1, x_2$ 分别表示 $(i_1, k-i_1)$ 和 $(i_2, k-i_2)$ 的前一步位置。
76
+
77
+ 时间复杂度 $O(n^3)$,空间复杂度 $O(n^3)$。其中 $n$ 表示网格的边长。
70
78
71
79
<!-- tabs:start -->
72
80
73
81
``` python
74
82
class Solution :
75
83
def cherryPickup (self , grid : List[List[int ]]) -> int :
76
84
n = len (grid)
77
- dp = [[[- inf] * n for _ in range (n)] for _ in range ((n << 1 ) - 1 )]
78
- dp [0 ][0 ][0 ] = grid[0 ][0 ]
85
+ f = [[[- inf] * n for _ in range (n)] for _ in range ((n << 1 ) - 1 )]
86
+ f [0 ][0 ][0 ] = grid[0 ][0 ]
79
87
for k in range (1 , (n << 1 ) - 1 ):
80
88
for i1 in range (n):
81
89
for i2 in range (n):
@@ -93,23 +101,21 @@ class Solution:
93
101
for x1 in range (i1 - 1 , i1 + 1 ):
94
102
for x2 in range (i2 - 1 , i2 + 1 ):
95
103
if x1 >= 0 and x2 >= 0 :
96
- dp[k][i1][i2] = max (
97
- dp[k][i1][i2], dp[k - 1 ][x1][x2] + t
98
- )
99
- return max (0 , dp[- 1 ][- 1 ][- 1 ])
104
+ f[k][i1][i2] = max (f[k][i1][i2], f[k - 1 ][x1][x2] + t)
105
+ return max (0 , f[- 1 ][- 1 ][- 1 ])
100
106
```
101
107
102
108
``` java
103
109
class Solution {
104
110
public int cherryPickup (int [][] grid ) {
105
111
int n = grid. length;
106
- int [][][] dp = new int [n * 2 ][n][n];
107
- dp [0 ][0 ][0 ] = grid[0 ][0 ];
112
+ int [][][] f = new int [n * 2 ][n][n];
113
+ f [0 ][0 ][0 ] = grid[0 ][0 ];
108
114
for (int k = 1 ; k < n * 2 - 1 ; ++ k) {
109
115
for (int i1 = 0 ; i1 < n; ++ i1) {
110
116
for (int i2 = 0 ; i2 < n; ++ i2) {
111
117
int j1 = k - i1, j2 = k - i2;
112
- dp [k][i1][i2] = Integer . MIN_VALUE ;
118
+ f [k][i1][i2] = Integer . MIN_VALUE ;
113
119
if (j1 < 0 || j1 >= n || j2 < 0 || j2 >= n || grid[i1][j1] == - 1
114
120
|| grid[i2][j2] == - 1 ) {
115
121
continue ;
@@ -121,14 +127,14 @@ class Solution {
121
127
for (int x1 = i1 - 1 ; x1 <= i1; ++ x1) {
122
128
for (int x2 = i2 - 1 ; x2 <= i2; ++ x2) {
123
129
if (x1 >= 0 && x2 >= 0 ) {
124
- dp [k][i1][i2] = Math . max(dp [k][i1][i2], dp [k - 1 ][x1][x2] + t);
130
+ f [k][i1][i2] = Math . max(f [k][i1][i2], f [k - 1 ][x1][x2] + t);
125
131
}
126
132
}
127
133
}
128
134
}
129
135
}
130
136
}
131
- return Math . max(0 , dp [n * 2 - 2 ][n - 1 ][n - 1 ]);
137
+ return Math . max(0 , f [n * 2 - 2 ][n - 1 ][n - 1 ]);
132
138
}
133
139
}
134
140
```
@@ -138,42 +144,49 @@ class Solution {
138
144
public:
139
145
int cherryPickup(vector<vector<int >>& grid) {
140
146
int n = grid.size();
141
- vector<vector<vector<int >>> dp (n << 1, vector<vector<int >>(n, vector<int >(n, -1e9)));
142
- dp [ 0] [ 0 ] [ 0] = grid[ 0] [ 0 ] ;
147
+ vector<vector<vector<int >>> f (n << 1, vector<vector<int >>(n, vector<int >(n, -1e9)));
148
+ f [ 0] [ 0 ] [ 0] = grid[ 0] [ 0 ] ;
143
149
for (int k = 1; k < n * 2 - 1; ++k) {
144
150
for (int i1 = 0; i1 < n; ++i1) {
145
151
for (int i2 = 0; i2 < n; ++i2) {
146
152
int j1 = k - i1, j2 = k - i2;
147
- if (j1 < 0 || j1 >= n || j2 < 0 || j2 >= n || grid[ i1] [ j1 ] == -1 || grid[ i2] [ j2 ] == -1) continue;
153
+ if (j1 < 0 || j1 >= n || j2 < 0 || j2 >= n || grid[ i1] [ j1 ] == -1 || grid[ i2] [ j2 ] == -1) {
154
+ continue;
155
+ }
148
156
int t = grid[ i1] [ j1 ] ;
149
- if (i1 != i2) t += grid[ i2] [ j2 ] ;
150
- for (int x1 = i1 - 1; x1 <= i1; ++x1)
151
- for (int x2 = i2 - 1; x2 <= i2; ++x2)
152
- if (x1 >= 0 && x2 >= 0)
153
- dp[ k] [ i1 ] [ i2] = max(dp[ k] [ i1 ] [ i2] , dp[ k - 1] [ x1 ] [ x2] + t);
157
+ if (i1 != i2) {
158
+ t += grid[ i2] [ j2 ] ;
159
+ }
160
+ for (int x1 = i1 - 1; x1 <= i1; ++x1) {
161
+ for (int x2 = i2 - 1; x2 <= i2; ++x2) {
162
+ if (x1 >= 0 && x2 >= 0) {
163
+ f[ k] [ i1 ] [ i2] = max(f[ k] [ i1 ] [ i2] , f[ k - 1] [ x1 ] [ x2] + t);
164
+ }
165
+ }
166
+ }
154
167
}
155
168
}
156
169
}
157
- return max(0, dp [ n * 2 - 2] [ n - 1 ] [ n - 1] );
170
+ return max(0, f [ n * 2 - 2] [ n - 1 ] [ n - 1] );
158
171
}
159
172
};
160
173
```
161
174
162
175
```go
163
176
func cherryPickup(grid [][]int) int {
164
177
n := len(grid)
165
- dp := make([][][]int, (n<<1)-1)
166
- for i := range dp {
167
- dp [i] = make([][]int, n)
168
- for j := range dp [i] {
169
- dp [i][j] = make([]int, n)
178
+ f := make([][][]int, (n<<1)-1)
179
+ for i := range f {
180
+ f [i] = make([][]int, n)
181
+ for j := range f [i] {
182
+ f [i][j] = make([]int, n)
170
183
}
171
184
}
172
- dp [0][0][0] = grid[0][0]
185
+ f [0][0][0] = grid[0][0]
173
186
for k := 1; k < (n<<1)-1; k++ {
174
187
for i1 := 0; i1 < n; i1++ {
175
188
for i2 := 0; i2 < n; i2++ {
176
- dp [k][i1][i2] = int(-1e9)
189
+ f [k][i1][i2] = int(-1e9)
177
190
j1, j2 := k-i1, k-i2
178
191
if j1 < 0 || j1 >= n || j2 < 0 || j2 >= n || grid[i1][j1] == -1 || grid[i2][j2] == -1 {
179
192
continue
@@ -185,14 +198,50 @@ func cherryPickup(grid [][]int) int {
185
198
for x1 := i1 - 1; x1 <= i1; x1++ {
186
199
for x2 := i2 - 1; x2 <= i2; x2++ {
187
200
if x1 >= 0 && x2 >= 0 {
188
- dp [k][i1][i2] = max(dp [k][i1][i2], dp [k-1][x1][x2]+t)
201
+ f [k][i1][i2] = max(f [k][i1][i2], f [k-1][x1][x2]+t)
189
202
}
190
203
}
191
204
}
192
205
}
193
206
}
194
207
}
195
- return max(0, dp[n*2-2][n-1][n-1])
208
+ return max(0, f[n*2-2][n-1][n-1])
209
+ }
210
+ ```
211
+
212
+ ``` ts
213
+ function cherryPickup(grid : number [][]): number {
214
+ const n: number = grid .length ;
215
+ const f: number [][][] = Array .from ({ length: n * 2 - 1 }, () =>
216
+ Array .from ({ length: n }, () => Array .from ({ length: n }, () => - Infinity )),
217
+ );
218
+ f [0 ][0 ][0 ] = grid [0 ][0 ];
219
+ for (let k = 1 ; k < n * 2 - 1 ; ++ k ) {
220
+ for (let i1 = 0 ; i1 < n ; ++ i1 ) {
221
+ for (let i2 = 0 ; i2 < n ; ++ i2 ) {
222
+ const [j1, j2]: [number , number ] = [k - i1 , k - i2 ];
223
+ if (
224
+ j1 < 0 ||
225
+ j1 >= n ||
226
+ j2 < 0 ||
227
+ j2 >= n ||
228
+ grid [i1 ][j1 ] == - 1 ||
229
+ grid [i2 ][j2 ] == - 1
230
+ ) {
231
+ continue ;
232
+ }
233
+ const t: number = grid [i1 ][j1 ] + (i1 != i2 ? grid [i2 ][j2 ] : 0 );
234
+ for (let x1 = i1 - 1 ; x1 <= i1 ; ++ x1 ) {
235
+ for (let x2 = i2 - 1 ; x2 <= i2 ; ++ x2 ) {
236
+ if (x1 >= 0 && x2 >= 0 ) {
237
+ f [k ][i1 ][i2 ] = Math .max (f [k ][i1 ][i2 ], f [k - 1 ][x1 ][x2 ] + t );
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ return Math .max (0 , f [n * 2 - 2 ][n - 1 ][n - 1 ]);
196
245
}
197
246
```
198
247
@@ -203,19 +252,14 @@ func cherryPickup(grid [][]int) int {
203
252
*/
204
253
var cherryPickup = function (grid ) {
205
254
const n = grid .length ;
206
- let dp = new Array (n * 2 - 1 );
207
- for (let k = 0 ; k < dp .length ; ++ k) {
208
- dp[k] = new Array (n);
209
- for (let i = 0 ; i < n; ++ i) {
210
- dp[k][i] = new Array (n).fill (- 1e9 );
211
- }
212
- }
213
- dp[0 ][0 ][0 ] = grid[0 ][0 ];
255
+ const f = Array .from ({ length: n * 2 - 1 }, () =>
256
+ Array .from ({ length: n }, () => Array .from ({ length: n }, () => - Infinity )),
257
+ );
258
+ f[0 ][0 ][0 ] = grid[0 ][0 ];
214
259
for (let k = 1 ; k < n * 2 - 1 ; ++ k) {
215
260
for (let i1 = 0 ; i1 < n; ++ i1) {
216
261
for (let i2 = 0 ; i2 < n; ++ i2) {
217
- const j1 = k - i1,
218
- j2 = k - i2;
262
+ const [j1 , j2 ] = [k - i1, k - i2];
219
263
if (
220
264
j1 < 0 ||
221
265
j1 >= n ||
@@ -226,21 +270,18 @@ var cherryPickup = function (grid) {
226
270
) {
227
271
continue ;
228
272
}
229
- let t = grid[i1][j1];
230
- if (i1 != i2) {
231
- t += grid[i2][j2];
232
- }
273
+ const t = grid[i1][j1] + (i1 != i2 ? grid[i2][j2] : 0 );
233
274
for (let x1 = i1 - 1 ; x1 <= i1; ++ x1) {
234
275
for (let x2 = i2 - 1 ; x2 <= i2; ++ x2) {
235
276
if (x1 >= 0 && x2 >= 0 ) {
236
- dp [k][i1][i2] = Math .max (dp [k][i1][i2], dp [k - 1 ][x1][x2] + t);
277
+ f [k][i1][i2] = Math .max (f [k][i1][i2], f [k - 1 ][x1][x2] + t);
237
278
}
238
279
}
239
280
}
240
281
}
241
282
}
242
283
}
243
- return Math .max (0 , dp [n * 2 - 2 ][n - 1 ][n - 1 ]);
284
+ return Math .max (0 , f [n * 2 - 2 ][n - 1 ][n - 1 ]);
244
285
};
245
286
```
246
287
0 commit comments