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

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

今天更新动态规划路径问题1,后续会继续更新其他有关动态规划的问题!动态规划的路径问题,顾名思义,就是和路径相关的问题。当然,我们是从最简单的找路径开始!

  • 动态规划的使用方法:
    1.确定状态并定义状态数组:(i,j)代表什么意思?dp[i][j]又是什么意思?
    2.确定状态转移方程,即递推公式
    3.确定边界条件并初始化
    4.确定遍历顺序
    5.状态转移
    6.输出结果

基础算法之——【动态规划之路径问题】1,“解锁编程之门:力扣刷题指南“,算法,动态规划,c++


一、LC 62 不同路径

LC 62 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

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

问总共有多少条不同的路径?
基础算法之——【动态规划之路径问题】1,“解锁编程之门:力扣刷题指南“,算法,动态规划,c++


方法一:深度优先搜索

代码如下:

class Solution {
private:
    int dfs(int m,int n,int i,int j){

        //行或列有至少一个越界
        if(i>m||j>n) return 0;

        //到达终点(在竖直方向达到m,水平方向达到n,也即坐标达到(m,n))
        if(i==m && j==n) return 1;

        //递归搜索(左子树和右子树)
        return dfs(m,n,i+1,j)+dfs(m,n,i,j+1);
    }
public:
    int uniquePaths(int m, int n) {
        
        //从根节点开始遍历
        int cnt=dfs(m,n,1,1);
        return cnt;

    }
};

方法二:动态规划(二维)

代码如下:

/*动态规划的使用方法:
1.确定状态并定义状态数组:(i,j)代表什么意思?dp[i][j]又是什么意思?
2.确定状态转移方程,即递推公式
3.确定边界条件并初始化
4.确定遍历顺序
5.状态转移
6.输出结果
*/
class Solution {

public:
    int uniquePaths(int m, int n) {
        //定义一个状态数组,用来存方法数      
        int dp[101][101]={0};

        //初始化状态数组
        for(int i=0;i<m;i++){
            dp[i][0]=1;
        }
        for(int j=0;j<n;j++){
            dp[0][j]=1;
        }

        //遍历
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                //状态转移
                dp[i][j]=dp[i][j-1]+dp[i-1][j];
            }
        }

        //返回结果
        return dp[m-1][n-1];
    }
};

方法三:动态规划(一维)

代码如下:

class Solution {
public:
    int uniquePaths(int m, int n) {
          
        //定义一维状态数组  
        int dp[101]={0};

        //初始化数组值为1,即相对于二维数组第一行全是1
        for(int i=0;i<n;i++){
            dp[i]=1;
        }

        //遍历
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                
                //状态转移:dp[j]指的是上一行的j,dp[j-1]指的是当前行左边的j;
                //每次状态转移都相当于先将上一行的运算拷贝过来,再加上从左面来的方案数
                dp[j]=dp[j-1]+dp[j];
            }
        }

        return dp[n-1];
      
    }
};

方法四:排列组合

代码如下:

class Solution {
public:
    int uniquePaths(int m, int n) {
        long long numerator = 1; // 初始化分子

        int denominator = m - 1; // 初始化分母

        int count = m - 1;//定义分子的乘积项的个数

        int t = m + n - 2;//定义分子的最大乘积项

        while (count--) {//分子累乘count项

            numerator *= (t--);
            while (denominator != 0 && numerator % denominator == 0) {

                //约分(也即除以公因数)
                numerator /= denominator;

                //约去一个公因数
                denominator--;
            }
        }
        return numerator;
    }
};

二、LC 63 不同路径II

LC 63 不同路径II
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

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

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。
基础算法之——【动态规划之路径问题】1,“解锁编程之门:力扣刷题指南“,算法,动态规划,c++



方法一:动态规划(二维)

代码如下:

 class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {

        //求出二维动态数组的行数
        int m=obstacleGrid.size();

        //求出二维动态数组的列数
        int n=obstacleGrid[0].size();

        //定义状态数组
        int dp[101][101]={0};
        
        //边界判断
        if(obstacleGrid[0][0]==1 || obstacleGrid[m-1][n-1]==1) return 0;

        //初始化状态数组
        dp[0][0]=1;

        //遍历
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                
                //如果是障碍物,则此路不通,路径数归零
                if(obstacleGrid[i][j]==1){
                     dp[i][j]=0;
                     continue;
                }

                //状态转移,此处和上面的一样
               if(i>0 && j>0) dp[i][j]=dp[i-1][j]+dp[i][j-1];
               else if(i>0) dp[i][j]=dp[i-1][j];
               else if(j>0) dp[i][j]=dp[i][j-1];

//也可以这样写
/*
 if(obstacleGrid[i][j]==0){
                      //状态转移,此处和上面的一样
               if(i>0 && j>0) dp[i][j]=dp[i-1][j]+dp[i][j-1];
               else if(i>0) dp[i][j]=dp[i-1][j];
               else if(j>0) dp[i][j]=dp[i][j-1];

                }
              
            }
            else continue;
*/
            }
        }
        return dp[m-1][n-1];

    }
};

方法二:动态规划(一维)

代码如下:

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if (obstacleGrid[0][0] == 1)
            return 0;
        vector<int> dp(obstacleGrid[0].size(),0);
        
        //初始化一维状态数组(第一行)
        for (int j = 0; j < dp.size() && obstacleGrid[0][j] == 0 ; ++j)
            if (j == 0)
                dp[j] = 1;
            else
                dp[j] = dp[j-1];

        //
        for (int i = 1; i < obstacleGrid.size(); ++i)//行
            for (int j = 0; j < dp.size(); ++j){//列

                if (obstacleGrid[i][j] == 1)
                    dp[j] = 0;

                else if (j != 0)
                    dp[j] = dp[j] + dp[j-1];
            }
        return dp.back();//返回最后一个状态对应值
    }
};

方法三:记忆化搜索

代码如下:

class Solution {
public:
    int m,n;
    vector<vector<int>>memo;
    vector<pair<int,int>>dir{{0,1},{1,0}};
    int uniquePathsWithObstacles(vector<vector<int>>& ob) {
            n=ob.size();
            m=ob[0].size();
            if(ob[0][0]==1||ob[n-1][m-1]==1){
                return 0;
            }
            memo.resize(n,vector<int>(m,0));
            return dfs(ob,0,0);
    }
    int dfs(vector<vector<int>>&ob,int i,int j){
        if(memo[i][j]!=0){
            return memo[i][j];
        }
        if(i==n-1&&j==m-1){
            memo[i][j]=1;
            return 1;
        }
        int cur=0;
        for(auto &d:dir){
            int x=i+d.first;
            int y=j+d.second;
            if(x>=0&&x<n&&y>=0&&y<m&&ob[x][y]==0){
                cur+=dfs(ob,x,y);
            }
        }
        memo[i][j]=cur;
        return memo[i][j];
    }
};

作者:Gallant MurdockrFZ
链接:https://leetcode.cn/problems/unique-paths-ii/solutions/2466610/dfsji-yi-hua-sou-suo-by-gallant-murdockr-e882/
来源:力扣(LeetCode)


三、LC 64 最小路径和

LC 64 最小路径和
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。
基础算法之——【动态规划之路径问题】1,“解锁编程之门:力扣刷题指南“,算法,动态规划,c++


方法一:动态规划(二维)

代码如下:

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {

        //定义一个二维状态数组
        int dp[201][201]={0};

        //初始化状态数组
        dp[0][0]=grid[0][0];

        //获得行数和列数
        int m=grid.size();
        int n=grid[0].size();

        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){

                //正常情况
                if(i>0 && j>0){
                    dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
                }

                //边界条件
                else if(i>0) dp[i][j]=dp[i-1][j]+grid[i][j];
                else if(j>0) dp[i][j]=dp[i][j-1]+grid[i][j];

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

    }
};

方法二:动态规划(一维)

代码如下:

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {

        //获取行数和列数
       int m=grid.size();
       int n=grid[0].size();

        //定义一维状态数组
       int dp[201]={0};

       //初始化第一行
       dp[0]=grid[0][0];
       for(int i=1;i<n;i++){
           dp[i]=grid[0][i]+dp[i-1];
       }

        //状态转移(配合滚动数组优化)
       for(int i=1;i<m;i++){
           for(int j=0;j<n;j++){
               //左边界
               if(j==0) dp[j]+=grid[i][j];

               //其他情况
               else dp[j]=min(dp[j-1],dp[j])+grid[i][j];
           }
       }
       return dp[n-1];

    }
};

我以前没怎么接触过动态规划,目前就是每天有空看看题,想想解题思路啥的,但愿有效果吧!
基础算法之——【动态规划之路径问题】1,“解锁编程之门:力扣刷题指南“,算法,动态规划,c++文章来源地址https://www.toymoban.com/news/detail-722428.html

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

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

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

相关文章

  • C++算法 —— 动态规划(2)路径问题

    每一种算法都最好看完第一篇再去找要看的博客,因为这样会帮你梳理好思路,看接下来的博客也就更轻松了。当然,我也会尽量在写每一篇时都可以让不懂这个算法的人也能边看边理解。 动规的思路有五个步骤,且最好画图来理解细节,不要怕麻烦。当你开始画图,仔细阅

    2024年02月06日
    浏览(35)
  • 用动态规划算法编程实现数字三角形问题

    如下所示为一个数字三角形: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 请编一个程序计算从顶至底的某一条路径,使该路径所经过的数字的总和最大。 思路:建立两个二位数组m(用来存储数字三角形),sum(用来存储数字三角形中每一个值得路径值);sum[i] [j]从最后一行开始存储; 如果当前

    2024年02月11日
    浏览(52)
  • acwing算法基础之动态规划--背包问题

    (零) 背包问题描述:有 N N N 个物品,每个物品的体积是 v i v_i v i ​ ,价值是 w i w_i w i ​ ,现有容量是 V V V 的背包,求这个背包能装下的物品的最大价值。 01背包问题:每个物品只有1个。 完全背包问题:每个物品有无穷多个。 多重背包问题:第 i i i 个物品有 s i s_i s

    2024年02月05日
    浏览(37)
  • 解锁动态规划:从斐波那契到高效算法

    👤作者介绍:10年大厂数据经营分析经验,现任大厂数据部门负责人。 会一些的技术:数据分析、算法、SQL、大数据相关、python 欢迎加入社区:码上找工作 作者专栏每日更新: LeetCode解锁1000题: 打怪升级之旅 python数据分析可视化:企业实战案例 备注说明:方便大家阅读,

    2024年04月15日
    浏览(32)
  • Python 算法基础篇:背包问题的动态规划解法

    背包问题是计算机科学中一个重要的组合优化问题,动态规划是解决该问题的高效算法技术。本篇博客将重点介绍背包问题的动态规划解法,包括状

    2024年02月16日
    浏览(31)
  • Acwing-基础算法课笔记之动态规划(背包问题)

    01背包中的0和1指的是放与不放,而且不能出现放多个的情况,背包只能放相同物品中的一个; 首先是对 d [ i ] [ j ] d[i][j] d [ i ] [ j ] 数组的解释,该数组表示的是只看前 i i i 个物品,总体积是 j j j 的情况下,总价值最大是多少; 不选第 i i i 个物品,只考虑前 i − 1 i-1 i −

    2024年04月17日
    浏览(38)
  • 算法基础复盘笔记Day09【动态规划】—— 背包问题

    ❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于 Java后端开发 ,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得 关注 、 点赞 、 收藏 、 评论 ⭐️⭐️⭐️ 📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉 1. 题目

    2023年04月22日
    浏览(35)
  • 动态规划|【路径问题】|931.下降路径最小和

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

    2024年04月13日
    浏览(33)
  • 【动态规划】路径问题

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

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

    题目描述: 状态表示: 设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日
    浏览(27)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包