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]);
    
        }
    }
    
  • 相关阅读:
    jQuery常用 遍历函数
    JS针对pc页面固定宽度在手机展示问题 <meta ...>
    关于窗口的一些小脚本
    关于 注册页面浏览器自动添加账号密码问题?
    一个完整的html 每个标签的含义
    rem与@media 的优缺点
    关于IE浏览器的一些思路
    jq 动态添加.active 实现导航效果
    CSS 常用样式 提高网页编写速度
    html5与js关于input[type='text']文本框value改变触发事件一些属性的区别oninput,onpropertychange,onchange和文本框的value点击全选状态onclick="select();"。做购物车页面时会要用到。
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13074971.html
Copyright © 2011-2022 走看看