动态规划(7)_路径问题_礼物的最大价值

一、题目解析

我们先来看一下题,题目告诉我们给了我们一个二数组frame,其中frame[i][j]为该位置的珠宝价值,我们只能从左上角也就是[0][0]位置开始拿珠宝,每次只能往右或者往下走一步,然题目问我们到达右下角的时候可以拿到的最高价值。相信大家都知道这道题让我们做什么了,好,接下来我们看一下怎么解决这道问题。

二、算法原理

1、状态表示

根据我们做前面几道题的经验加上题目要求,我们可以直接定义一个状态表示。

dp[i[[j]表示:到达[i][j]位置,取得的珠宝最高价值。

2、状态转移方程

根据题目的要求,我们有两种方式到达[i][j]位置,第一种是从[i-1][j]的位置到达[i][j]位置,另一种是从[i][j-1]的位置到达[i][j]位置,我们先来看第一种。

我们从[i-1][j]位置到[i][j],我们只要知道到达[i-1][j]的珠宝最高价值,在加上[i][j]位置的珠宝价值是不是就是[i][j]位置的价值呢?[i-1][j]的珠宝最高价值在哪里呢?不就在我们的状态表示里面吗?也就是dp[i-1][j]里面。

同理,我们从[i][j-1]位置到[i][j],也需要到达知道[i][j-1]的珠宝最高价值,它就在dp[i][j-1]里面,在加上[i][j]位置的价值即可。

题目要求的是最大的价值,因此我们仅需要取一个最大值即可。

因此状态转移方程:dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + frame[i][j]

3、初始化

初始化的时候看状态转移方程,当我们填dp[0][0]位置的是会用到dp[-1][[0]和dp[0][-1]的值,但是这两个位置越界了呀,因此我们创建dp表的时候可以多开一行多开一列,然后从dp[1][1]的位置填表,那么这个我们会用到dp[0][1]和dp[1][0]这两个位置的值,那么我们初始化成什么呢?dp[1][1]表示到达[1][1]时候的最大价值,最大价值是什么?不就是frame[0][0]吗?因此将这两个位置初始化为0即可。那么第一行和第一列的其它位置初始化为什么呢?其实也初始化为0即可。这个地方要注意frame数组下标的映射关系。因为我们多开了一行一列,因此它的下标需要-1的。

4、填表

从上往下,从左往右填表即可。

5、返回结果

因为多开了一行多开了一列,因此直接返回dp[m][n]即可。

三、编写代码

希望大家可以根据算法原理自己尝试编写一下代码。

LCR 166. 珠宝的最高价值 - 力扣(LeetCode)

class Solution 
{
public:
    int jewelleryValue(vector<vector<int>>& frame) 
    {
        int m = frame.size(), n = frame[0].size();
        //1、创建dp表
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
       //2、填表
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + frame[i - 1][j - 1];
        //3、返回值
        return dp[m][n];
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值