Java-реализация LeetCode 741: сбор вишни (DFS || Recursion || Passing Notes)

741. Сбор вишни

Сетка N x N представляет вишневое поле, и каждая сетка представлена ​​одним из следующих трех чисел:

0 означает, что сетка пуста, поэтому вы можете пересечь ее.
1 означает, что в этой сетке есть вишня, вы можете выбрать ее и пройти через нее.
-1 означает, что в этой сетке есть шипы, блокирующие ваш путь.
Ваша задача собрать как можно больше вишен, соблюдая при этом следующие правила:

Начиная с позиции (0, 0) и, наконец, достигая (N-1, N-1), вы можете идти только вниз или вправо и проходить только через действительные сетки (то есть вы можете пересекать сетки только со значениями 0 или 1). );
Когда вы достигнете (N-1, N-1), вы должны продолжать идти до тех пор, пока не вернетесь к (0, 0), вы можете идти только вверх или влево и проходить только через действительную сетку;
когда вы проходите сетку И эта сетка содержит вишню, вы выберете вишни, и сетка станет пустой (значение становится 0),
если между (0, 0) и (N-1, N-1) нет никого Путь, по которому можно пройти, ни одна вишня не может быть выбрана.
Пример 1:

Входные данные: сетка =
[[0, 1, -1],
[1, 0, -1],
[1, 1, 1]]
Выходные данные: 5
Объяснение:
Игрок начинает с (0,0) и проходит вниз Идите, идите вниз, идите направо, идите направо и достигните точки (2, 2).
В этой поездке в один конец было отобрано 4 вишни, и матрица стала [[0,1, -1], [0,0, -1], [0,0,0]].
Затем игрок прошел налево, вверх, вверх и влево, вернулся к исходной точке и взял еще одну вишню.
Во время путешествия было собрано 5 вишен, что является максимальным значением, которое можно выбрать.
Описание:

Сетка представляет собой двумерный массив N * N, диапазон значений N составляет 1 <= N <= 50.
Каждая сетка [i] [j] является числом в наборе {-1, 0, 1}.
Можно гарантировать, что начальная сетка [0] [0] и конечная сетка [N-1] [N-1] не будут равны -1.

PS: Этот
вопрос можно преобразовать в: я иду на две позиции за раз и могу только идти вниз или идти вправо.
Так как x + y моей позиции будет равен x + y другой позиции
Или используйте массив для сохранения координат

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]);

    }
}
Опубликовано 1 785 оригинальных статей · 30 000 лайков + · 4,44 миллиона просмотров

рекомендация

отblog.csdn.net/a1439775520/article/details/105482173