2.3 路径问题专题:剑指 Offer 47. 礼物的最大价值

动态规划解决剑指 Offer 47题:礼物的最大价值

1. 题目链接

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

2. 题目描述

在一个 m x n 的棋盘的每一格都放有一个礼物(价值非负),从棋盘的左上角出发,每次向右或向下移动一格,直到到达右下角。给定一个棋盘,计算从起点到终点所能拿到的礼物价值的最大总和。

示例

  • 输入:
    [ [1,3,1], [1,5,1], [4,2,1] ]
  • 输出:12
  • 解释:最优路径为 右 → 右 → 下 → 下,总和为 1 + 3 + 5 + 2 + 1 = 12

3. 示例分析

以示例输入为例:

  1. 起点 (0,0) 的值为 1,下一步可以选择向右到 (0,1) 或向下到 (1,0)
  2. 动态规划表 dp 会记录每个位置的最大累计值。
  3. 最终 dp[3][3](对应棋盘右下角)的值为 12,即最优路径的总和。

4. 算法思路

动态规划状态定义

  • 定义 dp[i][j] 表示从起点 (0,0) 到达棋盘位置 (i-1, j-1) 的最大累计价值(索引从 1 开始以避免越界)。

状态转移方程

  • 每个位置的最大价值等于其左侧或上侧的最大值加上当前格子的价值:
    dp[i][j] = frame[i-1][j-1] + max(dp[i-1][j], dp[i][j-1])

初始化技巧

  • 由于棋盘起点为 (0,0),对应的 dp[1][1] 初始化为 frame[0][0]。通过将 dp 数组的维度设为 (m+1) x (n+1),并隐式初始化为 0,避免了显式处理边界条件。

5. 边界条件与注意事项

  1. 空输入处理:若棋盘为空(m=0n=0),需返回 0(代码中未显式处理,实际应用需补充)。
  2. 单行或单列棋盘:路径唯一,直接累加所有值即可。
  3. 负价值场景:题目假设礼物价值非负,若允许负值需考虑路径选择逻辑是否变化。

6. 代码实现

class Solution {
public:
    int jewelleryValue(vector<vector<int>>& frame) {
        int m = frame.size(), n = frame[0].size();
        // 处理空输入的特殊情况
        if (m == 0 || n == 0) return 0;

        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = frame[i-1][j-1] + max(dp[i-1][j], dp[i][j-1]);
            }
        }
        
        return dp[m][n];
    }
};

代码解析

  1. 输入检查:添加了对空棋盘的处理,避免访问非法内存。
  2. 动态规划表填充:双重循环遍历每个位置,通过 max 函数选择左侧或上侧的最大路径值。
  3. 返回值dp[m][n] 对应棋盘右下角的最大累计价值。

时间复杂度O(mn),需遍历整个棋盘。
空间复杂度O(mn),动态规划表的空间开销。

通过动态规划逐格递推,代码简洁且高效,完美解决了棋盘最大路径和问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值