剑指offer-47

剑指 Offer 47. 礼物的最大价值

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

示例:

1
2
3
4
5
6
7
8
输入: 
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 13521 可以拿到最多价值的礼物

官方题解

题目说明:从棋盘的左上角开始拿格子里的礼物,并每次 向右 或者 向下 移动一格、直到到达棋盘的右下角。

根据题目说明,易得某单元格只可能从上边单元格或左边单元格到达。

设 $f(i,j)$ 为从棋盘左上角走至单元格 $(i,j)$ 的礼物的最大累计价值,易得到以下递推关系:$f(i,j)$等于 $f(i,j-1)$和 $f(i-1, j)$ 中的较大值加上当前单元格礼物 $grid(i,j)$。
$$
f(i,j) = max[f(i,j-1),f(i-1,j)] + grid(i,j)
$$
因此,可用动态规划解决此问题,以上公式便为转移方程。

image-20210628201920819
动态规划解析:
  • 状态定义:设动态规划矩阵 $dp$, $dp(i,j)$ 代表从棋盘的左上角开始,到达单元格 $(i,j)$ 时能拿到礼物的最大累计价值。

  • 转移方程:

    1. 当 $i=0$ 且 $j=0$,为起始元素;

    2. 当 $i=0$ 且 $j \neq 0$,为矩阵第一行元素,只可从左边到达;

    3. 当 $i \neq 0$ 且 $j = 0$,为矩阵第一列元素,只可从上边到达;

    4. 当 $i \neq 0$且 $j\neq 0$,可从左边或上边到达;
      $$
      d p(i, j)=\left{\begin{array}{ll}
      \operatorname{grid}(i, j) & , i=0, j=0 \
      \operatorname{grid}(i, j)+d p(i, j-1) & , i=0, j \neq 0 \
      \operatorname{grid}(i, j)+d p(i-1, j) & , i \neq 0, j=0 \
      \operatorname{grid}(i, j)+\max [d p(i-1, j), d p(i, j-1)] & , i \neq 0, j \neq 0
      \end{array}\right.
      $$

  • 初始状态: $dp[0][0] = grid[0][0]$,即到达单元格 $(0,0)$ 时能拿到礼物的最大累计价值为 $grid[0][0]$;

  • 返回值: $dp[m-1][n-1],;; dp[i][j-1],;;,m,n$ 分别为矩阵的行高和列宽,既返回 $dp$ 矩阵右下角元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def maxValue(self, grid) -> int:
# 遍历行
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]
作者

bd160jbgm

发布于

2021-06-27

更新于

2021-06-28

许可协议