Input: grid =[[0,1,-1],[1,0,-1],[1,1,1]]Output: 5Explanation: The player started at(0,0) and went down, down, right right to reach(2,2).4 cherries were picked up during this single trip, and the matrix becomes [[0,1,-1],[0,0,-1],[0,0,0]].Then, the player went left, up, up, left to return home, picking up one more cherry.The total number of cherries picked up is5, and thisis the maximum possible.
The problem can be transformed into finding the maximum cherries collected by two people starting from (0,0) and moving to (n-1,n-1) simultaneously, since the return trip is symmetric. At each step, both can move either right or down, and if they land on the same cell, only one cherry is picked. This allows us to use a 3D DP to represent the state.
Instead of using recursion and memoization, we can use an iterative approach to fill a 3D DP table. The key insight is that the two traversals (forward and backward) can be modeled as two people starting from (0,0) and moving to (n-1,n-1) simultaneously, and at each step, both can move either right or down. The DP state represents the maximum cherries collected when both are at certain positions after a given number of steps.
Let dp[k][i][j] be the maximum cherries collected when both persons have taken k steps, and are at positions (i, k-i) and (j, k-j) respectively.
Both persons start at (0,0). For each step k from 0 to 2n-2, iterate over all possible positions (i, k-i) and (j, k-j) that are within bounds and not on thorns.
For each state, consider all four ways the two persons could have arrived at their current positions (from left or above for each).
If both are at the same cell, only count the cherry once.
classSolution {
public:int cherryPickup(vector<vector<int>>& grid) {
int n = grid.size();
int maxK =2* n -2;
vector<vector<vector<int>>> dp(maxK +1, vector<vector<int>>(n, vector<int>(n, -100000)));
dp[0][0][0] = grid[0][0];
for (int k =1; k <= maxK; ++k) {
for (int i = max(0, k - (n -1)); i <= min(n -1, k); ++i) {
for (int j = max(0, k - (n -1)); j <= min(n -1, k); ++j) {
int y1 = k - i, y2 = k - j;
if (grid[i][y1] ==-1|| grid[j][y2] ==-1) continue;
int val = grid[i][y1];
if (i != j || y1 != y2) val += grid[j][y2];
int best =-100000;
for (int di =0; di <=1; ++di) {
for (int dj =0; dj <=1; ++dj) {
int pi = i - di, pj = j - dj;
if (pi >=0&& pj >=0)
best = max(best, dp[k -1][pi][pj]);
}
}
if (best >-100000)
dp[k][i][j] = best + val;
}
}
}
returnmax(0, dp[maxK][n -1][n -1]);
}
};
classSolution {
publicintcherryPickup(int[][] grid) {
int n = grid.length;
int maxK = 2 * n - 2;
int[][][] dp =newint[maxK + 1][n][n];
for (int k = 0; k <= maxK; k++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dp[k][i][j]=-100000;
dp[0][0][0]= grid[0][0];
for (int k = 1; k <= maxK; k++) {
for (int i = Math.max(0, k - (n - 1)); i <= Math.min(n - 1, k); i++) {
for (int j = Math.max(0, k - (n - 1)); j <= Math.min(n - 1, k); j++) {
int y1 = k - i, y2 = k - j;
if (grid[i][y1]==-1 || grid[j][y2]==-1) continue;
int val = grid[i][y1];
if (i != j || y1 != y2) val += grid[j][y2];
int best =-100000;
for (int di = 0; di <= 1; di++) {
for (int dj = 0; dj <= 1; dj++) {
int pi = i - di, pj = j - dj;
if (pi >= 0 && pj >= 0)
best = Math.max(best, dp[k - 1][pi][pj]);
}
}
if (best >-100000)
dp[k][i][j]= best + val;
}
}
}
return Math.max(0, dp[maxK][n - 1][n - 1]);
}
}
classSolution {
funcherryPickup(grid: Array<IntArray>): Int {
val n = grid.size
val maxK = 2 * n - 2val dp = Array(maxK + 1) { Array(n) { IntArray(n) { -100000 } } }
dp[0][0][0] = grid[0][0]
for (k in1..maxK) {
for (i in maxOf(0, k - (n - 1))..minOf(n - 1, k)) {
for (j in maxOf(0, k - (n - 1))..minOf(n - 1, k)) {
val y1 = k - i
val y2 = k - j
if (grid[i][y1] == -1|| grid[j][y2] == -1) continuevar v = grid[i][y1]
if (i != j || y1 != y2) v += grid[j][y2]
var best = -100000for (di in0..1) {
for (dj in0..1) {
val pi = i - di
val pj = j - dj
if (pi >=0&& pj >=0)
best = maxOf(best, dp[k - 1][pi][pj])
}
}
if (best > -100000)
dp[k][i][j] = best + v
}
}
}
return maxOf(0, dp[maxK][n - 1][n - 1])
}
}
classSolution:
defcherryPickup(self, grid: list[list[int]]) -> int:
n: int = len(grid)
max_k: int =2* n -2 dp: list[list[list[int]]] = [[[-100000] * n for _ in range(n)] for _ in range(max_k +1)]
dp[0][0][0] = grid[0][0]
for k in range(1, max_k +1):
for i in range(max(0, k - (n -1)), min(n -1, k) +1):
for j in range(max(0, k - (n -1)), min(n -1, k) +1):
y1, y2 = k - i, k - j
if grid[i][y1] ==-1or grid[j][y2] ==-1:
continue val = grid[i][y1]
if i != j or y1 != y2:
val += grid[j][y2]
best =-100000for di in (0, 1):
for dj in (0, 1):
pi, pj = i - di, j - dj
if pi >=0and pj >=0:
best = max(best, dp[k -1][pi][pj])
if best >-100000:
dp[k][i][j] = best + val
return max(0, dp[max_k][n -1][n -1])
impl Solution {
pubfncherry_pickup(grid: Vec<Vec<i32>>) -> i32 {
let n = grid.len();
let max_k =2* n -2;
letmut dp =vec![vec![vec![-100000; n]; n]; max_k +1];
dp[0][0][0] = grid[0][0];
for k in1..=max_k {
for i in k.saturating_sub(n -1)..=k.min(n -1) {
for j in k.saturating_sub(n -1)..=k.min(n -1) {
let y1 = k - i;
let y2 = k - j;
if grid[i][y1] ==-1|| grid[j][y2] ==-1 {
continue;
}
letmut val = grid[i][y1];
if i != j || y1 != y2 {
val += grid[j][y2];
}
letmut best =-100000;
for di in0..=1 {
for dj in0..=1 {
let pi = i asisize- di;
let pj = j asisize- dj;
if pi >=0&& pj >=0 {
best = best.max(dp[k -1][pi asusize][pj asusize]);
}
}
}
if best >-100000 {
dp[k][i][j] = best + val;
}
}
}
}
0.max(dp[max_k][n -1][n -1])
}
}