zoukankan      html  css  js  c++  java
  • Java实现 LeetCode 741 摘樱桃(DFS || 递推 || 传纸条)

    741. 摘樱桃

    一个N x N的网格(grid) 代表了一块樱桃地,每个格子由以下三种数字的一种来表示:

    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:

    输入: grid =
    [[0, 1, -1],
    [1, 0, -1],
    [1, 1, 1]]
    输出: 5
    解释:
    玩家从(0,0)点出发,经过了向下走,向下走,向右走,向右走,到达了点(2, 2)。
    在这趟单程中,总共摘到了4颗樱桃,矩阵变成了[[0,1,-1],[0,0,-1],[0,0,0]]。
    接着,这名玩家向左走,向上走,向上走,向左走,返回了起始点,又摘到了1颗樱桃。
    在旅程中,总共摘到了5颗樱桃,这是可以摘到的最大值了。
    说明:

    grid 是一个 N * N 的二维数组,N的取值范围是1 <= N <= 50。
    每一个 grid[i][j] 都是集合 {-1, 0, 1}其中的一个数。
    可以保证起点 grid[0][0] 和终点 grid[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]);
    
        }
    }
    
  • 相关阅读:
    28完全背包+扩展欧几里得(包子凑数)
    HDU 3527 SPY
    POJ 3615 Cow Hurdles
    POJ 3620 Avoid The Lakes
    POJ 3036 Honeycomb Walk
    HDU 2352 Verdis Quo
    HDU 2368 Alfredo's Pizza Restaurant
    HDU 2700 Parity
    HDU 3763 CDs
    POJ 3279 Fliptile
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13074728.html
Copyright © 2011-2022 走看看