zoukankan      html  css  js  c++  java
  • 剑指 Offer 47. 礼物的最大价值(动态规划dp)

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

    这道题,第一想法就是用动态规划,也找到了转移方程,但是呢,就是实现的过程有问题,来我们看看题解大佬的清晰分析。

    • 解法:动态规划

    1.为什么想到用动态规划?

    从棋盘的左上角开始拿格子里的礼物,并每次 向右 或者 向下 移动一格、直到到达棋盘的右下角。根据题目说明,易得某单元格只可能从上边单元格或左边单元格到达。

     这一步是可以得到的,OK?

    看,这是不是就是个动态规划典型情况?动态规划是把一个大问题拆解成一堆小问题,并且将一个问题拆成几个子问题,分别求解这些子问题,即可推断出大问题的解。

    2.动态规划具有以下性质:

    • 【无后效性】“未来与过去无关”,这就是无后效性。
    • 【最优子结构】大问题的最优解可以由小问题的最优解推出,这个性质叫做“最优子结构性质”

    我们可以定义状态dp,dp(i,j)代表从棋盘左上角开始,到达单元格(i,j)时能拿到礼物的最大累计价值。主要方法是每次通过改变grid单元格元素的值,将grid矩阵当作dp矩阵。(这里参考大佬的题解)

     代码

    class Solution:
        def maxValue(self, grid: List[List[int]]) -> int:
            if not grid:
                return 0
            for i in range(len(grid)):
                for j in range(len(grid[0])):
                    if i ==0 and j == 0:
                        continue
                    if i == 0:
                        grid[i][j] += grid[i][j-1]
                    elif j ==0:
                        grid[i][j] += grid[i-1][j]
                    else:
                        grid[i][j] += max(grid[i][j-1], grid[i-1][j])
            return grid[-1][-1]

    时间复杂度O(MN):分别为两个for循环遍历的矩阵长宽

    空间复杂度O(1):原地修改grid大小不用额外空间

    • 优化

    优化的目的是当grid很大,i=0或者j=0的情况仅仅占少数,相当于循环每轮都冗余了一次判断。因此,可先初始化矩阵第一行和第一列,再开始遍历递推。

    class Solution:
        def maxValue(self, grid: List[List[int]]) -> int:
            if not grid:
                return 0
            m, n = len(grid), len(grid[0])
            for j in range(1, n): #初始化第一行
                grid[0][j] += grid[0][j-1]
            for i in range(1, m): #初始化第一列
                grid[i][0] += grid[i-1][0]
    
            for i in range(1, len(grid)):
                for j in range(1, len(grid[0])):
                        grid[i][j] += max(grid[i][j-1], grid[i-1][j])
            return grid[-1][-1]

    参考:https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/solution/mian-shi-ti-47-li-wu-de-zui-da-jie-zhi-dong-tai-gu/

  • 相关阅读:
    xshell安装错解决方案
    (转)进程process和线程thread的关系
    selenium Gird
    python发布文件(windows)
    (转)ci
    selenium通过python字典获取配置
    selenium断言的分类
    C#从Image上读取文本
    C#屏幕截图
    WPF实现TextBox水印效果
  • 原文地址:https://www.cnblogs.com/yeshengCqupt/p/13508202.html
Copyright © 2011-2022 走看看