动态规划之路径问题

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

1. 不同路径(medium)

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

3.问题分析:
对于动态规划关于路径问题的分析,首先需要选取某个位置,然后以该位置为起点或者结尾进行分析。如这题dp数组中i位置的结果是需要i-1、i-2等位置算出来的,这种情况就以i位置为结尾进行分析。

  1. 状态表示:对于m*n的网格来说,每一个格子可以对应到一个二维数组中的元素,对于从起点到某点(i,j)由多少种不同路径是从起始位置进行计算,所以以(i,j)位置为结尾进行分析。用dp[i][j]表示:从起点位置到[i,j]位置处,一共有多少种方式。有时候是不知道状态表示是正确还是错误的,为此只能先往下分析
  2. 状态转移方程:对(i,j)位置进行分析,dp[i][j]表示从起点位置到[i , j]位置处,一共有多少种方式,那么怎样才能到达 [i , j] 这个位置?因为只能往下或者往右走,所以到达 [i , j] 位置可以是 [i - 1, j] 或者是 [i , j - 1]这两个位置,两个位置的值进行相加 ,就是到达[i , j]位置处总共的方式。因此状态转移方程为:dp[i , j] = dp[i - 1, j] + [i , j - 1]。
  3. 初始化:对于第一行第一列来说,进行-1操作会放生越界情况。可以用if语句判断一下,也可以添加一行一列,多出来的一行一列成为辅助节点,使⽤这种技巧要注意两个点:辅助结点⾥⾯的值要保证后续填表是正确的;下标的映射关系。初始化只将dp[0][1]位置初始化为1即可。
  4. 填表顺序:从上往下填每⼀⾏,在填写每⼀⾏的时候从左往右。
  5. 返回值:返回dp[m][n]。
    动态规划之路径问题,动态规划,算法

4.代码如下:

class Solution
{
public:
    int uniquePaths(int m, int n)
    {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); // 创建⼀个 dp表
        dp[0][1] = 1; // 初始化
        // 填表
        for (int i = 1; i <= m; i++) // 从上往下
            for (int j = 1; j <= n; j++) // 从左往右
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        // 返回结果
        return dp[m][n];
    }
};

2. 不同路径II(medium)

1.题目链接:不同路径II
2.题目描述
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
动态规划之路径问题,动态规划,算法

3.问题分析
这道题和不同路径I区别就是这道题中的网格有障碍物,所以大致分析思路是相同的,就比如这道题是以[i, j]位置为结尾进行分析,状态表示也相同。

  1. 状态表示:dp[i][j] 表示:⾛到 [i, j] 位置处,⼀共有多少种⽅式。
    以[i, j]位置为结尾进行分析,同上到题,到达 [i , j] 位置可以是 [i - 1, j] 或者是 [i , j - 1]这两个位置,两个位置的值进行相加 ,就是到达[i , j]位置处总共的方式;但是如果有障碍物呢?比如[i - 1, j] 或者是 [i , j - 1]其中有一个是障碍物,那么到达[i , j] 位置的所有方法就是其中一个某个不是障碍物的路径数。所以另一个有障碍的路径数为零,即遇到障碍物就不需要计算这个位置上的值,直接让它等于0。
  2. 状态转移方程:同上一题dp[i , j] = dp[i - 1, j] + [i , j - 1]。不过如果这个位置上有障碍物,那么就不需要计算这个位置上的值,直接让它等于 0 即可。
  3. 初始化:同上一题,可以添加⼀行,并且添加⼀列后,只需将dp[1][0]的位置初始化为1 即可。
  4. 填表顺序:从上往下填每⼀⾏,在填写每⼀⾏的时候从左往右。
  5. 返回值:返回dp[m][n]。

动态规划之路径问题,动态规划,算法4.代码如下

class Solution 
{
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) 
    {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        dp[0][1] = 1;
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                if (obstacleGrid[i - 1][j - 1] == 0)
                {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m][n];
    }
};

3. 礼物最大值(medium)

1.题目链接:礼物最大值
2.题目描述
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
动态规划之路径问题,动态规划,算法

3.问题分析
这道题和上述两道又有所不同,但都属于同种类型,所以方法大致一样。先进行状态表示:用dp[i][j] 表示:⾛到 [i, j] 位置处,此时的最⼤价值。上述两题是要算出路径数,所以将[i - 1, j] 的路径数与[i , j - 1]的路径数相加。而这道题是要求路径上的最大价值,可以将[i - 1, j] 路径上的价值数与[i , j - 1]路径上的价值数进行比较,保留两个中较大的值然后再加上grid[i,j]位置上的值即可。

  1. dp[i][j] 表⽰:⾛到 [i, j] 位置处,此时的最⼤价值
  2. 状态转移方程:从[i - 1, j] 位置,向下⾛⼀步,此时到达 [i, j] 位置能拿到的礼物价值为 dp[i - 1][j] + grid[i][j] ; 从 [i, j - 1] 位置,向右⾛⼀步,此时到达 [i, j] 位置能拿到的礼物价值为dp[i][j - 1] + grid[i][j]。
  3. 初始化:同上一题,可以添加⼀行,并且添加⼀列后,所有的值都为 0 即可。
  4. 填表顺序:从上往下填每⼀⾏,在填写每⼀⾏的时候从左往右。
  5. 返回值:返回dp[m][n]。

动态规划之路径问题,动态规划,算法

4.代码如下

class Solution
{
public:
    int maxValue(vector<vector<int>>& grid)
    {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));

        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]) + grid[i - 1][j - 1];

        return dp[m][n];
    }
};

4. 下降路径最小和(medium)

1.题目链接:下降路径最小和
2.题目描述
给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 的 最小和 。
下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)、(row + 1, col) 或者 (row + 1, col + 1) 。
动态规划之路径问题,动态规划,算法
3.问题分析
大致思路不变,先表示状态,用二维数组dp[i][j] 表⽰:到达 [i, j] 位置时,所有下降路径中的最⼩和。然后进行分析,上述所示的问题,因只能向左或向下移动,所以[i,j]的路径数是将[i - 1, j] 的路径数与[i , j - 1]的路径数相加;而这道题位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)、(row + 1, col) 或者 (row + 1, col + 1) ;以[i,j]为结尾进行分析,到达[i,j]位置的上一层应当是[i - 1, j - 1],[i - 1, j],[i - 1, j + 1]中三者最小的一个,然后加上matrix[i,j]的值,然后遍历依次填写dp表即可。其中有越界问题,如[0, j]或[i, n - 1]位置,可以用辅助结点来解决,增加两列,一列在起始,另一列在末尾;最后寻找最后一行最小的值即为下降路径最小和。

  1. dp[i][j] 表⽰:到达 [i, j] 位置时,所有下降路径中的最⼩和。
  2. dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j +1])) + matrix[i][j] 。
  3. 初始化:需要加上两列,所有的位置都初始化为⽆穷⼤,将dp表第一行初始为matrix第一行(左右两列的辅助结点是无穷大)
  4. 从上往下填每⼀⾏,在填写每⼀⾏的时候从左往右。
    4.代码如下
class Solution 
{
public:
    int minFallingPathSum(vector<vector<int>>& matrix) 
    {
        int n = matrix.size();
        //初始化dp表,全部初始化为无穷大
        vector<vector<int>> dp(n, vector<int>(n + 2, INT_MAX));
        //=将dp表第一行初始为matrix第一行
        for (int j = 0; j < n; ++j)
            dp[0][j + 1] = matrix[0][j];
        //从第二行第二列开始遍历
        for (int i = 1; i < n; ++i)
        {
            //在dp表中不是辅助结点的位置范围是1到n
            for (int j = 1; j <= n; ++j)
            {
                int x = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i - 1][j + 1]));
                dp[i][j] = x + matrix[i][j - 1]; //没有添加行,matrix对应的映射为i,j-1
            }
        }
        //寻找最后一行最小值
        int ret = dp[n - 1][0];
        for (int j = 1; j <= n; ++j)
            ret = min(ret, dp[n - 1][j]);
        return ret;
    }
};

5. 最⼩路径和(medium)

1.题目链接:最⼩路径和
2.题目描述
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
动态规划之路径问题,动态规划,算法

3.问题分析
这道题与上述题基本一致了,分析就略过。

  1. 状态表⽰:dp[i][j] 表⽰:到达 [i, j] 位置处,最⼩路径和是多少。
  2. 这道题是要求路径上的最小和,可以将[i - 1, j] 路径上的最小和与[i , j - 1]路径上的最小和进行比较,保留两个中较小的值然后再加上grid[i,j]位置上的值即可。
  3. 添加⼀⾏,并且添加⼀列后,所有位置的值可以初始化为⽆穷⼤,然后让dp[0][1] = dp[1][0] = 0 即可。
  4. 要返回的结果是dp[m][n]。因为添加了一行一列。
    4.代码如下
class Solution
{
public:
    int minPathSum(vector<vector<int>>& grid)
    {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
        dp[0][1] = dp[1][0] = 0;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
        return dp[m][n];
    }
};

6. 地下城游戏(hard)

1.题目链接:地下城游戏
2.题目描述
恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快解救公主,骑士决定每次只 向右 或 向下 移动一步。
返回确保骑士能够拯救到公主所需的最低初始健康点数。
注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。
动态规划之路径问题,动态规划,算法

3.问题分析
这道题已知骑士到达公主所在地,也就是右下角,骑士此时所剩健康点数为1 ,求到达终点时,起始位置生命健康值的最小点数。所以这道题应该从右下角开始遍历,至于怎么遍历,看如下分析:状态表示:dp[i][j] 表⽰:从 [i, j] 位置出发,到达终点时所需的最低初始健康点数; 以[i,j]位置为起点进行分析,有很多条路径可以到达终点,路径上有加血的,有减血的,我们要求什么?求的是血最多的时候?不是,求的是应该血量刚够过该路径的值也就是dungeon数组中路径求和过程中各个路径负数的最大值的绝对值,所以减去 dungeon[i][j]就是所需的生命值,如果为dp结果负数,就说明能量值很大,而dp[i][j] 表⽰:从 [i, j] 位置出发,到达终点时所需的最低初始健康点数,dp[i][j]大于0,出现负数就要赋值为1。负数就代表起始位置生命值最低值为负数,这很显然不肯能为负数
位置[i + 1, j]或者 [i, j + 1]可以到达[i, j] 位置,dp的位置表示最低点数,所以选取 [i + 1, j], [i, j + 1]两者中的较小值减去dungeon[i][j]就是dp[i][j]的最小值。文章来源地址https://www.toymoban.com/news/detail-671343.html

  1. dp[i][j] 表⽰:从 [i, j] 位置出发,到达终点时所需的最低初始健康点数。
  2. 状态转移方程:dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];如果dp[i][j] <= 0,则dp[i][j] = 1。
  3. 初始化:在本题中,在 dp 表最后⾯添加⼀⾏,并且添加⼀列后,所有的值都先初始化为⽆穷⼤,然后让dp[m][n - 1] = dp[m - 1][n] = 1 即可。
  4. 填表顺序:需要从下往上填每⼀⾏,每⼀⾏从右往左。
  5. 返回值:dp[0][0]。
    4.代码如下
class Solution
{
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon)
    {
        int m = dungeon.size(), n = dungeon[0].size();
        // 建表 + 初始化
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
        dp[m][n - 1] = dp[m - 1][n] = 1;
        // 填表
        for (int i = m - 1; i >= 0; i--)
        {
            for (int j = n - 1; j >= 0; j--)
            {
                dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
                if (dp[i][j] <= 0)
                {
                    dp[i][j] = 1;
                }
            }
        }
        // 返回结果
        return dp[0][0];
    }
};

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

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

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

相关文章

  • 基础算法之——【动态规划之路径问题】1

    今天更新动态规划路径问题1,后续会继续更新其他有关动态规划的问题!动态规划的路径问题,顾名思义,就是和路径相关的问题。当然,我们是从最简单的找路径开始! 动态规划的使用方法: 1.确定状态并定义状态数组:(i,j)代表什么意思?dp[i][j]又是什么意思? 2.确

    2024年02月07日
    浏览(39)
  • 动态规划|【路径问题】|931.下降路径最小和

    目录 题目 题目解析 思路 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 代码 931. 下降路径最小和 给你一个  n x n  的  方形  整数数组  matrix  ,请你找出并返回通过  matrix  的 下降路径   的   最小和  。 下降路径  可以从第一行中的任何元素开始,并从每一

    2024年04月13日
    浏览(42)
  • 动态规划-路径问题

    题目描述: 状态表示: 设dp[i][j]表示到达(i,j)位置时的路径数目。 状态转移方程: dp[i][j]=dp[i-1][j]+dp[i][j-1]。这里分析起来很简单,因为这算是很经典的问题了。机器人只能向下或者向右走,所以到达(i,j)就有两种方式,分别是从(i-1,j)向下以及(i,j-1)向右,那么到达(i,j)位置的

    2024年04月17日
    浏览(35)
  • C++--动态规划路径问题

    1.不同路径 力扣 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径

    2024年02月15日
    浏览(41)
  • 【动态规划】路径问题

    冻龟算法系列之路径问题 本文为动态规划的第二章:路径问题,重点讲解关于路径有关的问题,上一篇文章是一维的,那么路径问题就是二维的,通过题目可见需要创建二维的dp表,而以下将通过“解题”的方式去学习动归知识! 创建什么样的dp表,其实看题目就可以看出来

    2024年02月09日
    浏览(39)
  • 动态规划——路径问题

    目录 什么是路径问题? 练习 练习1:不同路径  练习2:不同路径II 练习3:珠宝的最高价值 练习4:下降路径最小和 练习5:地下城游戏 动态规划中的路径问题: 指在一个给定的网格中,从起点到终点有多条可能的路径,每条路径都有一个特定的权重或成本,动态规划路径问

    2024年04月27日
    浏览(43)
  • 动态规划之路径问题

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

    2024年02月11日
    浏览(46)
  • 【动态规划专栏】专题二:路径问题--------1.不同路径

    本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。 💓博主csdn个人主页:小小unicorn ⏩专栏分类:动态规划专栏 🚚代码仓库:小小unicorn的代码仓库🚚

    2024年02月20日
    浏览(44)
  • 【动态规划】路径问题_不同路径_C++

    题目链接:leetcode不同路径 目录 题目解析: 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目让我们求总共有多少条不同的路径可到达右下角; 由题可得: 机器人位于一个  m x n   网格; 机器人每次只能向下或者向右移动一步; 我们拿示例

    2024年02月05日
    浏览(38)
  • 【路径规划】基于动态窗口法DWA算法的机器人动态避障路径规划研究附Matlab实现

     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进, 代码获取、论文复现及科研仿真合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab完整代码及仿真定制内容点击👇 智能优化算法       神经网络预测       雷达通信    

    2024年02月03日
    浏览(59)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包