Cherry Pickup
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ grid.length ≤ 15 (a square n×n grid) - ◆
grid[i][j] is -1 (blocked), 0 (empty), or 1 (one cherry) - ◆
grid[0][0] and grid[n-1][n-1] are never -1
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Without Memoization
BruteThink of it as two trips made at the same time, both starting at the top-left corner and both only moving right or down, each step taken simultaneously so both trips are always the same number of steps in. At every step, each trip independently moves right or down, giving up to four combined moves, and a move into a blocked cell — or off the grid — simply isn't allowed. Whenever both trips are on the same cell, its cherry is only collected once. From any pair of positions, the most cherries collectible from there onward is this step's cherries (for one or both trips) plus whichever of the reachable next pairs of positions collects the most; once both trips reach the bottom-right corner, there's nothing left to collect but that cell itself. Trying every combination of moves finds the maximum, though the same pair of positions ends up recomputed whenever different routes funnel into it, and the whole result is floored at 0 in case no route through survives at all.
O(4^n)O(n)1class Solution {
2 private int[][] grid;
3 private int n;
4
5 public int cherryPickup(int[][] grid) {
6 this.grid = grid;
7 this.n = grid.length;
8 int result = solve(0, 0, 0);
9 return Math.max(result, 0);
10 }
11
12 private int solve(int r1, int c1, int r2) {
13 int c2 = r1 + c1 - r2;
14 if (r1 >= n || c1 >= n || r2 >= n || c2 >= n || grid[r1][c1] == -1 || grid[r2][c2] == -1) {
15 return Integer.MIN_VALUE;
16 }
17 if (r1 == n - 1 && c1 == n - 1) {
18 return grid[r1][c1];
19 }
20 int best = Integer.MIN_VALUE;
21 best = Math.max(best, solve(r1 + 1, c1, r2 + 1));
22 best = Math.max(best, solve(r1 + 1, c1, r2));
23 best = Math.max(best, solve(r1, c1 + 1, r2 + 1));
24 best = Math.max(best, solve(r1, c1 + 1, r2));
25 if (best == Integer.MIN_VALUE) return Integer.MIN_VALUE;
26 int cherries = grid[r1][c1];
27 if (r1 != r2) cherries += grid[r2][c2];
28 return cherries + best;
29 }
30}Optimal — Bottom-Up 2D Table Per Step
OptimalSince both trips always take the same number of steps to reach any given pair of rows, a trip's column is fixed once its row and the step count are known (column = step − row). That means the state only needs each trip's row, so track a table indexed by "trip 1's row" and "trip 2's row" holding the most cherries collectible so far after a given number of steps. Step 0 starts both trips together at the top-left corner. At every step after that, each new entry is this step's cherries (for the pair of cells, counted once if they coincide) plus the best entry reachable from the previous step across the up to four combined moves — each trip either stayed in the same row (moved right) or advanced a row (moved down) — skipping any move into a blocked cell or off the grid. After the final step, when both trips have reached the bottom-right corner, that entry holds the answer, floored at 0.
O(n³)O(n²)1class Solution {
2 public int cherryPickup(int[][] grid) {
3 int n = grid.length;
4 int[][] dp = new int[n][n];
5 for (int[] row : dp) Arrays.fill(row, Integer.MIN_VALUE);
6 if (grid[0][0] != -1) dp[0][0] = grid[0][0];
7 for (int s = 1; s <= 2 * n - 2; s++) {
8 int[][] ndp = new int[n][n];
9 for (int[] row : ndp) Arrays.fill(row, Integer.MIN_VALUE);
10 for (int r1 = 0; r1 < n; r1++) {
11 int c1 = s - r1;
12 if (c1 < 0 || c1 >= n || grid[r1][c1] == -1) continue;
13 for (int r2 = 0; r2 < n; r2++) {
14 int c2 = s - r2;
15 if (c2 < 0 || c2 >= n || grid[r2][c2] == -1) continue;
16 int best = Integer.MIN_VALUE;
17 for (int d1 = 0; d1 <= 1; d1++) {
18 for (int d2 = 0; d2 <= 1; d2++) {
19 int pr1 = r1 - d1, pr2 = r2 - d2;
20 if (pr1 < 0 || pr2 < 0) continue;
21 best = Math.max(best, dp[pr1][pr2]);
22 }
23 }
24 if (best == Integer.MIN_VALUE) continue;
25 int cherries = grid[r1][c1];
26 if (r1 != r2) cherries += grid[r2][c2];
27 ndp[r1][r2] = cherries + best;
28 }
29 }
30 dp = ndp;
31 }
32 return Math.max(dp[n - 1][n - 1], 0);
33 }
34}