741. Cherry picking
An N x N grid represents a cherry field, and each grid is represented by one of the following three numbers:
0 means the grid is empty, so you can cross it.
1 means there is a cherry in this grid, you can pick it and go through it.
-1 means there are thorns in this grid, blocking your way.
Your task is to pick up as many cherries as possible while observing the following rules:
Starting from position (0, 0) and finally arriving at (N-1, N-1), you can only walk down or to the right, and can only pass through valid grids (that is, you can only cross grids with values of 0 or 1 );
When you reach (N-1, N-1), you have to continue walking until you return to (0, 0), you can only walk up or to the left, and can only pass through the valid grid;
when you pass a grid And this grid contains a cherry, you will pick cherries and the grid will become empty (the value becomes 0);
if there is no one between (0, 0) and (N-1, N-1) The path that can be traversed, no cherry can be picked.
Example 1:
Input: grid =
[[0, 1, -1],
[1, 0, -1],
[1, 1, 1]]
Output: 5
Explanation: The
player starts from (0,0) and passes down Go, go down, go right, go right, and reach the point (2, 2).
In this one-way trip, a total of 4 cherries were picked, and the matrix became [[0,1, -1], [0,0, -1], [0,0,0]].
Then, the player walked left, up, up, and left, returned to the starting point, and picked another cherry.
During the journey, a total of 5 cherries were picked, which is the maximum value that can be picked.
Explanation:
grid is a two-dimensional array of N * N, the value range of N is 1 <= N <= 50.
Each grid [i] [j] is a number in the set {-1, 0, 1}.
It can be guaranteed that the starting grid [0] [0] and the ending grid [N-1] [N-1] will not be -1.
PS:
This question can be converted to look into: what I can only go two places and go down or go to the right
as so away, x me this one location + y will be equal to another location x + y
Or use an array to save the coordinates
class Solution {
public int cherryPickup(int[][] grid) {
int m = grid.length;
int memo[][][] = new int[m][m][m];
for (int[][] layer: memo)
for (int[] row: layer)
Arrays.fill(row, Integer.MIN_VALUE);
int res = dp(grid,memo,0,0,0);
return Math.max(res,0);
}
public int dp(int[][] grid,int[][][] memo,int r1,int c1, int r2){
int c2 =r1+c1-r2;
if(r1==grid.length||r2==grid.length||c1==grid.length||c2==grid.length||grid[r1][c1]==-1||grid[r2][c2]==-1){
return -99999;
}
if(r1==grid.length-1&&c1==grid.length-1){
return grid[r1][c1];
}
if(memo[r1][c1][r2]!=Integer.MIN_VALUE){
return memo[r1][c1][r2];
}
int ans = 0;
if(r1!=r2){
ans = max(dp(grid,memo,r1+1,c1,r2+1),dp(grid,memo,r1+1,c1,r2),dp(grid,memo,r1,c1+1,r2+1),dp(grid,memo,r1,c1+1,r2) ) + grid[r1][c1] + grid[r2][c2];
}else{
ans = max(dp(grid,memo,r1+1,c1,r2+1),dp(grid,memo,r1+1,c1,r2),dp(grid,memo,r1,c1+1,r2+1),dp(grid,memo,r1,c1+1,r2)) + grid[r1][c1];
}
memo[r1][c1][r2] = ans;
return ans;
}
public int max(int a, int b,int c,int d){
a = Math.max(a,b);
a = Math.max(a,c);
a = Math.max(a,d);
return a;
}
}
class Solution {
public int cherryPickup(int[][] grid) {
int N = grid.length;
int[][] dp = new int[N + 1][N + 1];
for (int[] row : dp) {
Arrays.fill(row, Integer.MIN_VALUE);//使用了N+1,因此边界值也设置为MIN_VALUE
}
dp[N - 1][N - 1] = grid[N - 1][N - 1];
//sum表示一共要走的步数,也就是所谓的递增就好,不需要使用三维数组k,当前走第k步,一共要走2*N-2步(n-1)*2,下标的话就是2N-3
for (int sum = 2 * N - 3; sum >= 0; sum--) {
for (int i1 = Math.max(0, sum - N + 1); i1 <= Math.min(N - 1, sum); i1++) {//倒序
for (int i2 = i1; i2 <= Math.min(N - 1, sum); i2++) {
int j1 = sum - i1;
int j2 = sum - i2;
if (grid[i1][j1] == -1 || grid[i2][j2] == -1) {
dp[i1][i2] = Integer.MIN_VALUE;
} else {
if (i1 != i2 || j1 != j2) {
//不重合在同一个点,则获取的最大值=A的格子+B的格子+AB往哪个方向走,也就是上一个状态是怎么来得,
dp[i1][i2] = grid[i1][j1] + grid[i2][j2] + Math.max(Math.max(dp[i1][i2 + 1], dp[i1 + 1][i2]), Math.max(dp[i1][i2], dp[i1 + 1][i2 + 1]));
} else {
dp[i1][i2] = grid[i1][j1] + Math.max(Math.max(dp[i1][i2 + 1], dp[i1 + 1][i2]), Math.max(dp[i1][i2], dp[i1 + 1][i2 + 1]));
}
}
}
}
}
return Math.max(0,dp[0][0]);
}
}