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

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

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

在这里插入图片描述

文章目录

  • 一、LC 62 不同路径
      • 方法一:深度优先搜索
      • 方法二:动态规划(二维)
      • 方法三:动态规划(一维)
      • 方法四:排列组合
  • 二、LC 63 不同路径II
      • 方法一:动态规划(二维)
      • 方法二:动态规划(一维)
      • 方法三:记忆化搜索
  • 三、LC 64 最小路径和
      • 方法一:动态规划(二维)
      • 方法二:动态规划(一维)


一、LC 62 不同路径

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

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

问总共有多少条不同的路径?
在这里插入图片描述


方法一:深度优先搜索

代码如下:

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,即相对于二维数组第一行全是1for(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 来表示。
在这里插入图片描述



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

代码如下:

 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;elsedp[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 ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。
在这里插入图片描述


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

代码如下:

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];}
};

我以前没怎么接触过动态规划,目前就是每天有空看看题,想想解题思路啥的,但愿有效果吧!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/128384.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode竞赛---第 366 场周赛

Problem: 100103. 分类求和并作差 &#x1f4da; 题目&#xff1a;给你两个正整数 n 和 m 。 现定义两个整数 num1 和 num2 &#xff0c;如下所示&#xff1a; num1&#xff1a;范围 [1, n] 内所有 无法被 m 整除 的整数之和。num1&#xff1a;范围 [1, n] 内所有 无法被 m 整…

漏洞复现--Juniper Networks Junos OS EX远程命令执行漏洞(CVE-2023-36845)

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

机器学习---RBM、KL散度、DBN

1. RBM 1.1 BM BM是由Hinton和Sejnowski提出的一种随机递归神经网络&#xff0c;可以看做是一种随机生成的 Hopfield网络&#xff0c;是能够通过学习数据的固有内在表示解决困难学习问题的最早的人工神经网络之 一&#xff0c;因样本分布遵循玻尔兹曼分布而命名为BM。BM由二…

如何在VS2022中进行调试bug,调试的快捷键,debug与release之间有什么区别

什么是bug 在学习编程的过程中&#xff0c;应该都听说过bug吧&#xff0c;那么bug这个词究竟是怎么来的呢&#xff1f; 其实Bug的本意是“虫子”或者“昆虫”&#xff0c;在1947年9月9日&#xff0c;格蕾丝赫柏&#xff0c;一位为美国海军工作的电脑专家&#xff0c;也是最早…

JMeter压测如何分配业务比例?

在进行综合场景压测时&#xff0c;由于不同的请求&#xff0c;要求所占比例不同&#xff0c;那如何实现呢&#xff1f; 有人说将这些请求分别放到单独的线程组下&#xff0c;然后将线程组的线程数按照比例进行配置&#xff0c;这种方法不是很好&#xff0c;想想&#xff0c;不…

C++ 学习系列 -- std::list

一 std::list 介绍 list 是 c 中的序列式容器&#xff0c;其实现是双向链表&#xff0c;每个元素都有两个指针&#xff0c;分别指向前一个节点与后一个节点 链表与数组都是计算机常用的内存数据结构&#xff0c;与数组连续内存空间不一样的地方在于&#xff0c;链表的空间是不…

《计算机视觉中的多视图几何》笔记(13)

13 Scene planes and homographies 本章主要讲述两个摄像机和一个世界平面之间的射影几何关系。 我们假设空间有一平面 π \pi π&#xff0c;平面上的一点为 x π x_{\pi} xπ​。 x π x_{\pi} xπ​分别在两幅图像 P , P ′ P, P P,P′上形成了 x , x ′ x, x x,x′。 那…

【1++的Linux】之文件(一)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;初识文件二&#xff0c;文件接口 一&#xff0c;初识文件 文件就是文件内容属性。因此对文件的操作无非就是对文件内容的操作和对文件属性的操作。 我们访问…

办公技巧:Excel日常高频使用技巧

目录 1. 快速求和&#xff1f;用 “Alt ” 2. 快速选定不连续的单元格 3. 改变数字格式 4. 一键展现所有公式 “CTRL ” 5. 双击实现快速应用函数 6. 快速增加或删除一列 7. 快速调整列宽 8. 双击格式刷 9. 在不同的工作表之间快速切换 10. 用F4锁定单元格 1. 快速求…

java项目中git的.ignore文件设置

在Git中&#xff0c;ignore是用来指定Git应该忽略的故意不被追踪的文件。它并不影响已经被Git追踪的文件。我们可以通过.ignore文件在Git中指定要忽略的文件。 当我们执行git add命令时&#xff0c;Git会检查.gitignore文件&#xff0c;并自动忽略这些文件和目录。这样可以避免…

Rust Http 性能测试框架/工具

在Rust中&#xff0c;有几个常用的性能测试框架和工具可用于对HTTP性能进行测试。以下是其中一些&#xff1a; 1、Criterion&#xff1a;Criterion是一个通用的性能测试框架&#xff0c;可以用于测试各种类型的代码性能&#xff0c;包括HTTP性能。你可以使用Criterion来编写和运…

进阶指针(五)—— 指针笔试题

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 &#x1f388;相关博文&#xff1a;进阶C语言&#xff08;一&#xff09;、进阶C语言&#xff08;二&#xff09;、进阶C语言&#xff08;三&#xff09;、进阶指针&#xff08;四&#xff0…