【算法】——动态规划题目讲解

这篇具有很好参考价值的文章主要介绍了【算法】——动态规划题目讲解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本期继续为大家带来的是关于动态规划类题目的讲解,对于这类题目大家一定要多加练习,争取掌握。

(一)不同路径

链接如下:62. 不同路径

  • 题目如下:

动态规划题解,算法,算法,动态规划,c++

算法思路:

  • 1. 状态表⽰:

 对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式:

  • i. 从 [i, j] 位置出发;
  • ii. 从起始位置出发,到达 [i, j] 位置。

这⾥选择第⼆种定义状态表⽰的⽅式:

  • dp[i][j] 表⽰:⾛到 [i, j] 位置处,⼀共有多少种⽅式。

  • 2. 状态转移⽅程:

简单分析⼀下。如果 dp[i][j] 表⽰到达 [i, j] 位置的⽅法数,那么到达 [i, j] 位置之 前的⼀⼩步,有两种情况:

  • i. 从 [i, j] 位置的上⽅( [i - 1, j] 的位置)向下⾛⼀步,转移到 [i, j] 位置;
  • ii. 从 [i, j] 位置的左⽅( [i, j - 1] 的位置)向右⾛⼀步,转移到 [i, j] 位置。

由于我们要求的是有多少种⽅法,因此状态转移⽅程就呼之欲出了:

 💨  dp[i][j] = dp[i - 1] [j] + dp[i][j - 1] 


  • 3. 初始化:

可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:

  • i. 辅助结点⾥⾯的值要「保证后续填表是正确的」;
  • ii. 「下标的映射关系」

在本题中,「添加⼀⾏」,并且「添加⼀列」后,只需将 dp[0][1] 的位置初始化为 1 即可。


  • 4. 填表顺序:

根据「状态转移⽅程」的推导来看,填表的顺序就是「从上往下」填每⼀⾏,在填写每⼀⾏的时候 「从左往右」


  • 5. 返回值:

根据「状态表⽰」,我们要返回 dp[m][n] 的值。


代码如下:

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> arr(m+1,vector<int>(n+1,0));
        arr[0][1] = 1;

        for(int i=1; i<= m; ++i){
            for(int j=1; j<= n; j++){
                arr[i][j] = arr[i-1][j] + arr[i][j-1];
            }
        }
         // 返回结果
        return arr[m][n];
    }
};

性能分析:

  • 时间复杂度:O(mn)。

  • 空间复杂度:O(mn)。


(二)不同路径||

链接如下:63. 不同路径 II

题目如下:

动态规划题解,算法,算法,动态规划,c++

 

算法思路:

本题为不同路径的变型,只不过有些地⽅有「障碍物」,只要在「状态转移」上稍加修改就可解决。

  • 1. 状态表⽰:

对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式:

  • i. 从 [i, j] 位置出发;
  • ii. 从起始位置出发,到达 [i, j] 位置。

这⾥选择第⼆种定义状态表⽰的⽅式:

  • dp[i][j] 表⽰:⾛到 [i, j] 位置处,⼀共有多少种⽅式。

  • 2. 状态转移:

简单分析⼀下。如果 dp[i][j] 表⽰到达 [i, j] 位置的⽅法数,那么到达 [i, j] 位置之 前的⼀⼩步,有两种情况:

  • i. 从 [i, j] 位置的上⽅( [i - 1, j] 的位置)向下⾛⼀步,转移到 [i, j] 位置;
  • ii. 从 [i, j] 位置的左⽅( [i, j - 1] 的位置)向右⾛⼀步,转移到 [i, j] 位置。

但是, [i - 1, j] 与 [i, j - 1] 位置都是可能有障碍的,此时从上⾯或者左边是不可能 到达 [i, j] 位置的,也就是说,此时的⽅法数应该是 0。 由此我们可以得出⼀个结论,只要这个位置上「有障碍物」,那么我们就不需要计算这个位置上的值,直接让它等于 0 即可。


  • 3. 初始化:

可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:

  • i.    辅助结点⾥⾯的值要「保证后续填表是正确的」;
  • ii. 「下标的映射关系」

在本题中,添加⼀⾏,并且添加⼀列后,只需将 dp[1][0] 的位置初始化为 1 即可。


  • 4. 填表顺序:

根据「状态转移」的推导,填表的顺序就是「从上往下」填每⼀⾏,每⼀⾏「从左往右」。


  • 5. 返回值:

根据「状态表⽰」,我们要返回的结果是 dp[m][n] 。


代码如下:

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int len = obstacleGrid.size();
        int widelen=obstacleGrid[0].size();

        vector<vector<int>> arr(len+1,vector<int>(widelen+1,0));
        arr[0][1] = 1;

        for(int i=1; i<= len; ++i){
            for(int j=1; j<= widelen; ++j){
                if(obstacleGrid[i - 1][j - 1] == 0)
                    arr[i][j] = arr[i-1][j] + arr[i][j-1];
            }
        }
        return arr[len][widelen];
    }
};

性能分析:

  • 时间复杂度:O(mn)。

  • 空间复杂度:O(mn)。

 


(三)礼物的最⼤价值

链接如下:剑指 Offer 47. 礼物的最大价值

题目如下:

动态规划题解,算法,算法,动态规划,c++

算法思路:

  • 1. 状态表⽰: 

对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式:

  • i. 从 [i, j] 位置出发,巴拉巴拉;
  • ii. 从起始位置出发,到达 [i, j] 位置,巴拉巴拉。

这⾥选择第⼆种定义状态表⽰的⽅式:

  • dp[i][j] 表⽰:⾛到 [i, j] 位置处,此时的最⼤价值。

  • 2. 状态转移⽅程:

对于 dp[i][j] ,我们发现想要到达 [i, j] 位置,有两种⽅式:

  • i. 从 [i, j] 位置的上⽅ [i - 1, j] 位置,向下⾛⼀步,此时到达 [i, j] 位置能 拿到的礼物价值为 dp[i - 1][j] + grid[i][j] ;
  • ii. 从 [i, j] 位置的左边 [i, j - 1] 位置,向右⾛⼀步,此时到达 [i, j] 位置能 拿到的礼物价值为 dp[i][j - 1] + grid[i][j]

我们要的是最⼤值,因此状态转移⽅程为:

  •  💨   dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j] 。

  • 3. 初始化:

可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:

  • i. 辅助结点⾥⾯的值要「保证后续填表是正确的」;
  • ii. 「下标的映射关系」。

在本题中,「添加⼀⾏」,并且「添加⼀列」后,所有的值都为 0 即可。


  • 4. 填表顺序:

根据「状态转移⽅程」,填表的顺序是「从上往下填写每⼀⾏」,「每⼀⾏从左往右」。


  • 5. 返回值:

根据「状态表⽰」,我们应该返回 dp[m][n] 的值。


代码如下:

class Solution {
public:
    int maxValue(vector<vector<int>>& grid) {
        int len = grid.size();
        int wide = grid[0].size();
        vector<vector<int>> dp(len + 1, vector<int>(wide + 1));
        for(int i = 1; i <= len; i++){
            for(int j = 1; j <= wide; j++){
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
            }
        }
        return dp[len][wide];
    }
};

性能分析:

  • 时间复杂度:O(mn)。

  • 空间复杂度:O(mn)。


以上便是本期动态规划的几道题目,大家做题时按照上述的“五步走”战略去分析思考,我相信大家都可以做对,文章来源地址https://www.toymoban.com/news/detail-685758.html

到了这里,关于【算法】——动态规划题目讲解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode题目详解】第九章 动态规划part06 完全背的讲解 518. 零钱兑换 II 377. 组合总和 Ⅳ (day44补)

    # 完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品都有无限个(也就是可以放入背包多次) ,求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一不同的地方就是,每种物品有无限件 。

    2024年02月09日
    浏览(37)
  • LeetCode算法题解(动态规划)|LeetCoed62. 不同路径、LeetCode63. 不同路径 II

    题目链接:62. 不同路径 题目描述: 一个机器人位于一个  m x n   网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示例 1: 示例 2:

    2024年02月05日
    浏览(52)
  • 算法 动态规划 及Java例题讲解

    动态规划 (英语:Dynamic programming,简称 DP ),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题 。 简单来说,动态规划其

    2024年01月22日
    浏览(45)
  • LeetCode算法题解(动态规划)|LeetCode343. 整数拆分、LeetCode96. 不同的二叉搜索树

    题目链接:343. 整数拆分 题目描述: 给定一个正整数  n  ,将其拆分为  k  个  正整数  的和(  k = 2  ),并使这些整数的乘积最大化。 返回  你可以获得的最大乘积  。 示例 1: 示例 2: 提示: 2 = n = 58 算法分析: 定义dp数组及下标含义: dp[i]表述正整数i拆分成k个正整数

    2024年02月04日
    浏览(41)
  • 算法题目题单+题解——图论

    本文为自己做的一部分图论题目,作为题单列出,持续更新。 题单由题目链接和题解两部分组成,题解部分提供简洁题意,代码仓库:Kaiser-Yang/OJProblems。 对于同一个一级标题下的题目,题目难度尽可能做到递增。 题目链接:Luogu P3547 [POI2013] CEN-Price List 题解: 题目链接:

    2024年02月19日
    浏览(37)
  • 动态规划2:题目

    目录 第1题 Fibonacci 第2题 字符串分割(Word Break) .第3题 三角矩阵(Triangle) 第4题 路径总数(Unique Paths) 第5题 最小路径和(Minimum Path Sum) 第6题 背包问题 第7题 回文串分割(Palindrome Partitioning) 第8题 编辑距离(Edit Distance) 第9题 不同子序列(Distinct Subsequences) 分析问题: 1. 状态定义F(i):第

    2024年02月06日
    浏览(43)
  • 动态规划题目练习

    动态规划背包问题-CSDN博客 动态规划基础概念-CSDN博客 题目描述 棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河

    2024年04月25日
    浏览(36)
  • 【题解 | 基础动态规划】:数字三角形

    链接: [USACO1.5] [IOI1994]数字三角形 Number Triangles 观察下面的数字金字塔。 写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。 在上面的样例中,从 7 → 3 → 8 → 7 → 5 7 to 3 to 8 to 7 to 5 7 →

    2024年04月14日
    浏览(51)
  • 【LeetCode】动态规划类题目详解

    所有题目均来自于LeetCode,刷题代码使用的Python3版本 如果某一个问题有重叠的子问题,则使用动态规划进行求解是最有效的。 动态规划中每一个状态一定是由上一个状态推导出来的,这一点区别于贪心算法 动态规划五部曲 确定dp数组以及下标的含义 确定递推公式 dp数组如何

    2024年04月11日
    浏览(48)
  • 代码随想录 动态规划-基础题目

    目录 509.斐波那契数  70.爬楼梯 746.使用最小花费爬楼梯 62.不同路径 63.不同路径|| 343.整数拆分 96.不同的二叉树 509. 斐波那契数 简单 斐波那契数  (通常用  F(n)  表示)形成的序列称为  斐波那契数列  。该数列由  0  和  1  开始,后面的每一项数字都是前面两项数字的和

    2024年03月18日
    浏览(76)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包