【剑指offer】46.礼物的最大价值

总目录:

算法之旅导航目录

 

1.问题描述

在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
如输入这样的一个二维数组,
[
[1,3,1],
[1,5,1],
[4,2,1]
]
那么路径 1→3→5→2→1 可以拿到最多价值的礼物,价值为12

 

2.问题分析

注意这并不是贪心算法,都需要建立状态转移方程

dp[rowId][colId] = max(dp[rowId][colId-1], dp[rowId-1][colId]) + grid[rowId][colId];

 1记忆化搜索

建立dp表,建完表之后即可直接返回指定坐标的dp值,也需要状态转移方程

2动态规划

不需要建立dp表,直接把dp值放在原表中


3.代码实例

记忆化搜索

 1 #include <algorithm>
 2 class Solution {
 3   public:
 4     /**
 5      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 6      *
 7      *
 8      * @param grid int整型vector<vector<>>
 9      * @return int整型
10      */
11     //返回值:-1:没有前一个dp,0:左侧dp较大,1:上侧dp较大
12     vector<vector<int>> dpMap;
13     int getMaxDp(vector<vector<int> >& grid,
14                  int rowId, int colId) {
15         //超限
16         if (rowId < 0 || colId < 0) {//不能再移动
17             return 0;
18         }
19 
20         //该单元格的计算尚需计算
21         if (dpMap[rowId][colId] <= 0) {
22             int leftDp = colId <= 0 ? 0 : getMaxDp(grid, rowId, colId - 1);
23             int upDp = rowId <= 0 ? 0 : getMaxDp(grid, rowId - 1, colId);
24             dpMap[rowId][colId] = max(leftDp, upDp) + grid[rowId][colId];
25         }
26 
27         return dpMap[rowId][colId];
28     }
29 
30     int maxValue(vector<vector<int> >& grid) {
31         if (grid.size() <= 0 || grid[0].size() <= 0) {
32             return 0;
33         }
34 
35         int rowCnt = grid.size();
36         int colCnt = grid[0].size();
37 
38         //计算dpMap
39         for (int i = 0; i < rowCnt; i++) {//行遍历
40             dpMap.push_back(vector<int> {});
41             for (int j = 0; j < colCnt; j++) {//列遍历
42                 dpMap[i].push_back(0);
43                 dpMap[i][j] = getMaxDp(grid, i, j);
44             }
45         }
46 
47         return dpMap[rowCnt - 1][colCnt - 1];
48     }
49 };
View Code

动态规划

 1 class Solution {
 2 public:
 3     int maxValue(vector<vector<int> >& grid) {
 4         int m = grid.size();
 5         int n = grid[0].size();
 6         //第一列只能来自上方
 7         for(int i = 1; i < m; i++)
 8             grid[i][0] += grid[i - 1][0];
 9         //第一行只能来自左边
10         for(int i = 1; i < n; i++)
11             grid[0][i] += grid[0][i - 1];
12         //遍历后续每一个位置
13         for(int i = 1; i < m; i++)
14             for(int j = 1; j < n; j++)
15                 //增加来自左边的与上边的之间的较大值
16                 grid[i][j] += max(grid[i - 1][j], grid[i][j - 1]);
17         return grid[m - 1][n - 1];
18     }
19 };

 

posted @ 2022-11-20 17:54  啊原来是这样呀  阅读(29)  评论(0)    收藏  举报