Skip to content

Commit 7f50a50

Browse files
chore: Merge pull request #10 from saulmaldonado/feat/cherry-pickup-ii
cherry pickup ii
2 parents 6f8ecdf + 872316e commit 7f50a50

File tree

7 files changed

+281
-0
lines changed

7 files changed

+281
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Cherry Pickup II
2+
3+
## Difficulty
4+
5+
![Hard](https://img.shields.io/badge/hard-d9534f?style=for-the-badge&logoColor=white)
6+
7+
## Problem:
8+
9+
Given a rows x cols matrix grid representing a field of cherries. Each cell in grid represents the number of cherries that you can collect.
10+
11+
You have two robots that can collect cherries for you, Robot #1 is located at the top-left corner (0,0) , and Robot #2 is located at the top-right corner (0, cols-1) of the grid.
12+
13+
Return the maximum number of cherries collection using both robots by following the rules below:
14+
15+
- From a cell (i,j), robots can move to cell (i+1, j-1) , (i+1, j) or (i+1, j+1).
16+
- When any robot is passing through a cell, It picks it up all cherries, and the cell becomes an empty cell (0).
17+
- When both robots stay on the same cell, only one of them takes the cherries.
18+
- Both robots cannot move outside of the grid at any moment.
19+
- Both robots should reach the bottom row in the grid.
20+
21+
<!-- any examples -->
22+
23+
### Example 1:
24+
25+
![Example 1](./images/image1.png)
26+
27+
```
28+
Input: grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]
29+
Output: 24
30+
Explanation: Path of robot #1 and #2 are described in color green and blue respectively.
31+
Cherries taken by Robot #1, (3 + 2 + 5 + 2) = 12.
32+
Cherries taken by Robot #2, (1 + 5 + 5 + 1) = 12.
33+
Total of cherries: 12 + 12 = 24.
34+
```
35+
36+
### Example 2:
37+
38+
![Example 2](./images/image2.png)
39+
40+
```
41+
Input: grid = [[1,0,0,0,0,0,1],[2,0,0,0,0,3,0],[2,0,9,0,0,0,0],[0,3,0,5,4,0,0],[1,0,2,3,0,0,6]]
42+
Output: 28
43+
Explanation: Path of robot #1 and #2 are described in color green and blue respectively.
44+
Cherries taken by Robot #1, (1 + 9 + 5 + 2) = 17.
45+
Cherries taken by Robot #2, (1 + 3 + 4 + 3) = 11.
46+
Total of cherries: 17 + 11 = 28.
47+
```
48+
49+
### Example 4:
50+
51+
```
52+
Input: grid = [[1,0,0,3],[0,0,0,3],[0,0,3,3],[9,0,3,3]]
53+
Output: 22
54+
```
55+
56+
### Example 5:
57+
58+
```
59+
Input: grid = [[1,1],[1,1]]
60+
Output: 4
61+
```
62+
63+
### Constraints
64+
65+
`rows == grid.length`
66+
67+
`cols == grid[i].length`
68+
69+
`2 <= rows, cols <= 70`
70+
71+
`0 <= grid[i][j] <= 100 `
72+
73+
<details>
74+
<summary>Solutions (Click to expand)</summary>
75+
76+
### Explanation
77+
78+
<!-- solution explanation -->
79+
80+
Since each robot can only one move down grid's height `h` each time it collects cherries then the problem be simplified as finding the best possible movements the robots can make at each level.
81+
82+
The possible movements of each robot are straight down `i` down-left `i-1` and down-right `i+1`. There are a possible 9 different combinations of movements the robots can make for each level from each movement. This amounts to 9^h possible movement that can be made. We can use dfs function that recursively traverses the each one of these possible moves to until the bottom, calculates the cherries collected for each move, takes the max out of all three, and adds it to each move of the the upper level to repeat the process.
83+
84+
Since that are a total of 9^h operations need to completely traverse the grid, we need a way to reduce the amount of possible recalculations and recursive that happen when traversing previously familiar paths. In order to reduce the total number of operations we can use memoization to save max number of cherries that can collected from the bottom to the cell (bottom up dp). This will short-circuit recursive calls and dramatically reduce the number of operations need to traverse the entire grid. Since the robots can only move down 1 cell for each movement we can use a 3d array with of size `h * i * j`
85+
86+
<!-- relative links to solution files. {title} should be replaced with the name of the problem in `kebab-case` -->
87+
88+
- [JavaScript](./cherry-pickup-ii.js)
89+
- [TypeScript](./cherry-pickup-ii.ts)
90+
- [Java](./cherry-pickup-ii.java)
91+
- [Go](./cherry-pickup-ii.go)
92+
</details>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package cherrypickupii
2+
3+
func cherryPickup(grid [][]int) int {
4+
dp := make([][][]int, len(grid))
5+
6+
// create 3d array
7+
for i := range dp {
8+
dp[i] = make([][]int, len(grid[0]))
9+
for j := range dp[i] {
10+
dp[i][j] = make([]int, len(grid[0]))
11+
}
12+
}
13+
14+
return traverse(grid, dp, 0, 0, len(grid[0])-1)
15+
}
16+
17+
func traverse(grid [][]int, dp [][][]int, h int, i int, j int) int {
18+
dirs := [3]int{-1, 0, 1}
19+
cherries := grid[h][i]
20+
21+
if j != i {
22+
cherries += grid[h][j]
23+
}
24+
25+
if h == len(grid)-1 {
26+
dp[h][i][j] = cherries
27+
return cherries
28+
}
29+
30+
if dp[h][i][j] > 0 {
31+
return dp[h][i][j]
32+
}
33+
34+
max := 0
35+
36+
for _, dir1 := range dirs {
37+
rob1 := i + dir1
38+
for _, dir2 := range dirs {
39+
rob2 := j + dir2
40+
41+
if rob1 >= 0 && rob1 < len(grid[0]) && rob2 >= 0 && rob2 < len(grid[0]) {
42+
res := traverse(grid, dp, h+1, rob1, rob2)
43+
44+
if res > max {
45+
max = res
46+
}
47+
}
48+
}
49+
}
50+
dp[h][i][j] = max + cherries
51+
return dp[h][i][j]
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
class Solution {
2+
public int[] dirs = new int[] { -1, 0, 1 };
3+
4+
public int cherryPickup(int[][] grid) {
5+
6+
int dp[][][] = new int[grid.length][grid[0].length][grid[0].length];
7+
8+
return traverse(grid, dp, 0, 0, grid[0].length - 1);
9+
}
10+
11+
private int traverse(int[][] grid, int[][][] dp, int h, int i, int j) {
12+
int cherries = grid[h][i];
13+
14+
if (j != i) {
15+
cherries += grid[h][j];
16+
}
17+
18+
if (h == grid.length - 1) {
19+
dp[h][i][j] = cherries;
20+
return cherries;
21+
}
22+
23+
if (dp[h][i][j] > 0) {
24+
return dp[h][i][j];
25+
}
26+
27+
int max = 0;
28+
29+
for (int dir1 : dirs) {
30+
int rob1 = i + dir1;
31+
for (int dir2 : dirs) {
32+
int rob2 = j + dir2;
33+
34+
if (rob1 >= 0 && rob1 < grid[0].length && rob2 >= 0 && rob2 < grid[0].length) {
35+
max = Math.max(traverse(grid, dp, h + 1, rob1, rob2), max);
36+
}
37+
}
38+
}
39+
40+
dp[h][i][j] = max + cherries;
41+
return dp[h][i][j];
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @param {number[][]} grid
3+
* @return {number}
4+
*/
5+
function cherryPickup(grid) {
6+
const dp = new Array(grid.length)
7+
.fill(undefined)
8+
.map(() => new Array(grid[0].length).fill(undefined).map(() => new Array(grid[0].length)));
9+
10+
return traverse(grid, dp, 0, 0, grid[0].length - 1);
11+
}
12+
13+
function traverse(grid, dp, h, i, j) {
14+
const dirs = [1, 0, -1];
15+
16+
let cherries = grid[h][i];
17+
18+
if (j !== i) {
19+
cherries += grid[h][j];
20+
}
21+
22+
if (h === grid.length - 1) {
23+
dp[h][i][j] = cherries;
24+
return cherries;
25+
}
26+
27+
if (dp[h][i][j] !== undefined) {
28+
return dp[h][i][j];
29+
}
30+
31+
let max = 0;
32+
33+
for (let dir1 of dirs) {
34+
const rob1 = i + dir1;
35+
for (let dir2 of dirs) {
36+
const rob2 = j + dir2;
37+
38+
if (rob1 >= 0 && rob1 < grid[0].length && rob2 >= 0 && rob2 < grid[0].length) {
39+
max = Math.max(traverse(grid, dp, h + 1, rob1, rob2), max);
40+
}
41+
}
42+
}
43+
44+
dp[h][i][j] = max + cherries;
45+
46+
return dp[h][i][j];
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @param {number[][]} grid
3+
* @return {number}
4+
*/
5+
function cherryPickup(grid: number[][]): number {
6+
const dp: number[][][] = new Array(grid.length)
7+
.fill(undefined)
8+
.map(() => new Array(grid[0].length).fill(undefined).map(() => new Array(grid[0].length)));
9+
10+
return traverse(grid, dp, 0, 0, grid[0].length - 1);
11+
}
12+
13+
function traverse(grid: number[][], dp: number[][][], h: number, i: number, j: number): number {
14+
const dirs: number[] = [1, 0, -1];
15+
16+
let cherries: number = grid[h][i];
17+
18+
if (j !== i) {
19+
cherries += grid[h][j];
20+
}
21+
22+
if (h === grid.length - 1) {
23+
dp[h][i][j] = cherries;
24+
return cherries;
25+
}
26+
27+
if (dp[h][i][j] !== undefined) {
28+
return dp[h][i][j];
29+
}
30+
31+
let max = 0;
32+
33+
for (let dir1 of dirs) {
34+
const rob1 = i + dir1;
35+
for (let dir2 of dirs) {
36+
const rob2 = j + dir2;
37+
38+
if (rob1 >= 0 && rob1 < grid[0].length && rob2 >= 0 && rob2 < grid[0].length) {
39+
max = Math.max(traverse(grid, dp, h + 1, rob1, rob2), max);
40+
}
41+
}
42+
}
43+
44+
dp[h][i][j] = max + cherries;
45+
46+
return dp[h][i][j];
47+
}
Loading
Loading

0 commit comments

Comments
 (0)