leetcode:礼物的最大价值

题目来源:力扣

题目描述:

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
=============================================
示例 1:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
===========================================

审题:

本题属于一道较简单的动态规划类题目.还是按照步骤一步步来分析.刚开始学习动态规划时,就像小时候解题一样,一步步理清自己的思路是非常重要的.按步骤慢慢来.

  • 分析最优子结构
    假设我们当前位于位置(i, j),我们想计算从该位置出发所能拿到的最多价值礼物, 由于我们每一步可以向右移动或向下移动,因此假设我们知道位置(i+1, j)以及位置(i, j+1)处我们所能拿到的最多价值礼物,我们便可以作出判断,在位置(i, j)处,我们应该向右还是向下移动. 基于该最优子结构,我们进一步分析子问题是否存在重叠. 分析不难发现, 为了计算(i, j)处最优方案,我们需要计算(i, j+1)处最优方案.而为了计算(i-1, j+1), 我们同样需要计算(i, j+1)处最优方案, 因此子问题存在重叠

  • 分析状态变量
    该问题状态变量较为简单, 即为当前所处位置. 由于是二维坐标, 因此我们可以使用二维数组存储每一状态处的最优方案. S[i][j]表示从位置(i, j)出发, 所能拿到的价值.

  • 确定状态转移方程
    S [ i ] [ j ] = g r i d [ i ] [ j ] + m a x ( S [ i + 1 ] [ j ] , S [ i ] [ j + 1 ] ) S[i][j] = grid[i][j] + max(S[i+1][j], S[i][j+1]) S[i][j]=grid[i][j]+max(S[i+1][j],S[i][j+1])
    其中基础情形为 S [ g r i d . l e n g t h − 1 ] [ g r i d [ 0 ] . l e n g t h − 1 ] = g r i d [ g r i d . l e n g t h − 1 ] [ g r i d [ 0 ] . l e n g t h − 1 ] S[grid.length-1][grid[0].length-1] = grid[grid.length-1][grid[0].length-1] S[grid.length1][grid[0].length1]=grid[grid.length1][grid[0].length1]
    因此, 从左上角出发, 所能获取的最多价值礼物为S[0][0];

java算法:

class Solution {
    public int maxValue(int[][] grid) {
        //状态变量为当前位置
        int S[][] = new int[grid.length][grid[0].length];
        int row = grid.length;
        int col = grid[0].length;
        //基础情形
        S[row-1][col-1] = grid[row-1][col-1];
        
        for(int i = row-1; i >= 0; i--){
            for(int j = col-1; j >= 0; j--){
                if(i + 1 < row){
                    S[i][j] = Math.max(S[i][j], grid[i][j] + S[i+1][j]);
                }
                if(j+1 < col){
                    S[i][j] = Math.max(S[i][j], grid[i][j] + S[i][j+1]);
                }
            }
        }
        return S[0][0];
    }
}
降低空间复杂度值O(1)

在初始版本中,由于我们使用额外的数组S保存各状态时的最优方案, 因此空间复杂度为O(MN). 通过分析, 我们发现我们可以直接更改grid[i][j]上的元素, 在计算完(i, j)处最优方案后,使用grid[i][j]储存位置(i, j)处最优方案.

class Solution {
    public int maxValue(int[][] grid) {
        //状态变量为当前位置
        //int S[][] = new int[grid.length][grid[0].length];
        int row = grid.length;
        int col = grid[0].length;
        for(int i = row-1; i >= 0; i--){
            for(int j = col-1; j >= 0; j--){
                int sum = 0;
                if(i + 1 < row){
                    sum = Math.max(sum, grid[i+1][j]);
                }
                if(j+1 < col){
                    sum = Math.max(sum,grid[i][j+1]);
                }
                grid[i][j] += sum;
            }
        }
        return grid[0][0];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值