不同路径 II(力扣LeetCode)动态规划

不同路径 II

题目描述

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

示例 1:

在这里插入图片描述
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  • 向右 -> 向右 -> 向下 -> 向下
  • 向下 -> 向下 -> 向右 -> 向右

示例 2:

在这里插入图片描述
输入:obstacleGrid = [[0,1],[0,0]]
输出:1

提示:

  • m == obstacleGrid.length
  • n == obstacleGrid[i].length
  • 1 <= m, n <= 100
  • obstacleGrid[i][j] 为 0 或 1

动规五部曲:

  1. 确定dp数组(dp table)以及下标的含义
    dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。
  2. 确定递推公式
    递推公式和62.不同路径⼀样,dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。
    但这⾥需要注意⼀点,因为有了障碍,(i, j)如果就是障碍的话应该就保持初始状态(初始状态为0)。
    所以代码为:
if (obstacleGrid[i][j] == 0) { // 当(i, j)没有障碍的时候,再推导dp[i][j]
	dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
  1. dp数组如何初始化
    在不同路径不同路径中我们给出如下的初始化:
vector<vector<int>> dp(m, vector<int>(n, 0)); // 初始值为0
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;

因为从(0, 0)的位置到(i, 0)的路径只有⼀条,所以dp[i][0]⼀定为1,dp[0][j]也同理。
但如果(i, 0) 这条边有了障碍之后,障碍之后(包括障碍)都是⾛不到的位置了,所以障碍之后的dp[i][0]应该还是
初始值0。
如图:
在这里插入图片描述
下标(0, j)的初始化情况同理。
所以本题初始化代码为:

vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;

注意代码⾥for循环的终⽌条件,⼀旦遇到obstacleGrid[i][0] == 1的情况就停⽌dp[i][0]的赋值1的操作,dp[0][j]同理
4. 确定遍历顺序
从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出,⼀定是从左到右⼀层⼀层遍历,这样保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]⼀定是有数值。
代码如下:

for (int i = 1; i < m; i++) {
	for (int j = 1; j < n; j++) {
		if (obstacleGrid[i][j] == 1) continue;
		dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
	}
}
  1. 举例推导dp数组
    拿示例1来举例如题:
    在这里插入图片描述
    对应的dp table 如图:
    在这里插入图片描述
    如果这个图看不懂,建议再理解⼀下递归公式,然后照着⽂章中说的遍历顺序,⾃⼰推导⼀下!

力扣提交代码

c++

class Solution {
public:
	int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
		int m = obstacleGrid.size();
		int n = obstacleGrid[0].size();
		if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0
			return 0;
		vector<vector<int>> dp(m, vector<int>(n, 0));
		for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
		for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
		for (int i = 1; i < m; i++) {
			for (int j = 1; j < n; j++) {
				if (obstacleGrid[i][j] == 1) continue;
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
			}
		}
		return dp[m - 1][n - 1];
	}
};

c语言

int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obstacleGridColSize) 
{
    int n=obstacleGridSize;// 定义障碍物网格行数
    int m=obstacleGridColSize[0];// 定义障碍物网格列数
    //如果在起点或终点出现了障碍,直接返回0
    if(obstacleGrid[0][0]==1||obstacleGrid[n-1][m-1]==1)    return 0;

    int i,j;
    int dp[110][110]={0};//所有元素先初始化为0
    //初始化dp数组
    for(i=0;i<n&&obstacleGrid[i][0]==0;i++) dp[i][0]=1;//第一行如果遇到障碍物,则后面为0
    for(j=0;j<m&&obstacleGrid[0][j]==0;j++) dp[0][j]=1;//第一列如果遇到障碍物,则后面为0

    for(i=1;i<n;i++)
    {
        for(j=1;j<m;j++)
        {
            if(obstacleGrid[i][j]==1)   continue;//遇到障碍物就跳过继续
            dp[i][j]=dp[i-1][j]+dp[i][j-1];
        }
    }
    return dp[n-1][m-1];
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

freerots启动过程分析(qemu仿真RISC-V架构为例)

1、前言 本文是基于qemu上virt板子适配的freertos系统源码进行讲解qemu安装可参考博客&#xff1a;《qemu源码下载和安装》&#xff1b;freertos移植到qemu上运行可参考博客&#xff1a;《移植freertos到qemu上运行》&#xff1b; 2、汇编代码部分 汇编文件&#xff1a;FreeR…

qt实现一个安卓测试小工具

qt实现一个安卓测试小工具 最终效果&#xff1a;目录结构源码gui.py 主要是按钮&#xff0c;文本控制代码main.py 主要是逻辑代码gui.spec 是打包使用的adb.ui 最终效果&#xff1a; 目录结构 上面2个是打包的生成的不用管 源码 gui.py 主要是按钮&#xff0c;文本控制代码…

vue3怎么提升效率的?为什么vue3比vue2快?效率提升主要在哪些方面?

官方文档中说vue3在 客户端渲染效率比vue2提升了1.3~2倍&#xff0c; SSR渲染效率比vue2提升了2~3倍&#xff0c;那么究竟是怎么提升的呢&#xff1f; 一、静态提升 在 vue3项目中的package.json文件中&#xff0c;可以看到这个 vue/compiler-sfc&#xff0c;它是用来解析(.v…

数据在内存中的存储练习题

数据在内存中的存储练习题 文章目录 数据在内存中的存储练习题1. 练习一2.练习二3. 练习三4. 练习四5. 练习五6. 练习六7. 总结 1. 练习一 #include <stdio.h>int main() {char a -1;signed b -1;unsigned char c -1;printf("a %d b %d c %d", a, b, c)…

PHP+vue+elementui高校学生社团信息管理系统o7q4a

社团是由高校用户依据兴趣爱好自愿组成&#xff0c;按照章程自主开展活动的用户组织。高校社团是实施素质教育的重要途径和有效方式&#xff0c;在加强校园文化建设、提高用户综合素质、引导用户适应社会、促进用户交流等方面发挥着重要作用&#xff0c;是新形势下有效凝聚用户…

Echarts legend图例配置项 设置位置 显示隐藏

Echarts 官网完整配置项 https://echarts.apache.org/zh/option.html#legend 配置项 legend: { }设置图例为圆形 icon: circle,//设置图例为圆形设置图例位置 top: 20%//距离顶部百分之20//y:bottom 在底部显示设置图例 宽度 高度 itemWidth: 10,//设置图例宽度 itemHeight: …

PCL 计算点云图中任意两点的欧式距离

目录 一、算法原理二、代码实现三、结果展示四、相关链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 使用PCL实现在可视化界面上用鼠标点选两个点,输出两点的坐标和两点之间的欧式距离。 二、代码…

HttpRunner原来还能这么用,大开眼界!!!

hook机制 Httprunner 框架中的 hook 机制相当于unittest框架中的 setup , teardown 函数&#xff0c;用来进行测试用例执行之前的环境初始化以及测试用例执行完毕之后的环境清理操作。 httprunner 中的 hooks 机制可以用在测试用例层级也可以用在测试步骤层级&#xff0c;其关键…

OSG编程指南<十三>:OSG渲染状态

1、前言 在 OSG 中存在两棵树&#xff0c;即场景树和渲染树。渲染树是一棵以 StateSet 和 RenderLeaf 为节点的树&#xff0c;它可以做到 StateSet 相同的 RenderLeaf 同时渲染而不用切换 OpenGL状态&#xff0c;并且做到尽量少但在多个不同 State 间切换。渲染树在 CullVisito…

01 项目架构

关于我 曾经就职于蚂蚁金服&#xff0c;多年的后端开发经验&#xff0c;对微服务、架构这块研究颇深&#xff0c;同时也是一名热衷于技术分享、拥抱开源技术的博主。 个人技术公众号&#xff1a;码猿技术专栏个人博客&#xff1a;www.java-family.cn 前期一直在更新《Spring…

sqli-labs关卡21(基于cookie被base64编码的报错盲注)通关思路

文章目录 前言一、回顾上一关知识点二、靶场需要了解的前置知识1、什么是base64编码&#xff1f; 三、靶场第二十一关通关思路1、判断注入点2、爆数据库名3、爆数据库表4、爆数据库列5、爆数据库关键信息 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于…

Funbox9_GaoKao通过NC获取反向shell

一. 发现主机 arp-scan -l -I eth0 找打GaoKao主机IP地址 173.30.1.128 二. Nmap扫描主机 nmap -A -T5 172.30.1.128 -A &#xff1a;系统探测&#xff0c;版本检测&#xff0c;脚本扫描&#xff0c;路由跟踪 -T(0-5)&#xff1a;数字越大速度越快(准确度低)&#xff0c;数字越…

vue+echarts实现依赖关系无向网络拓扑结图节点折叠展开策略

目录 引言 一、设计 1. 树状图&#xff08;不方便呈现节点之间的关系&#xff0c;次要考虑&#xff09; 2. 力引导依赖关系图 二、力引导关系图 三、如何实现节点的Open Or Fold 1. 设计逻辑 节点展开细节 节点收缩细节 代码实现 四、结果呈现 五、完整代码 引言 我…

离散数学-集合论基础

3.1集合的基本概念 1&#xff09;集合及元素 2&#xff09;集合的表示 3&#xff09;集合的关系 4&#xff09;特殊集合 3.2集合的运算 并、交、差、对称差 3.3集合的划分与覆盖 3.4排斥包含管理 3.1集合的基本概念 1&#xff09;集合及元素 将某种具有同种属性的个体…

扩散模型实战(十三):ControlNet结构以及训练过程

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 扩散模型实战&#xff08;四&#xff…

振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(9)

注解目录 1、znFAT 的起源 1.1 源于论坛 &#xff08;那是一个论坛文化兴盛的年代。网友 DIY SDMP3 播放器激起了我的兴趣。&#xff09; 1.2 硬盘 MP3 推了我一把 &#xff08;“坤哥”的硬盘 MP3 播放器&#xff0c;让我深陷 FAT 文件系统不能自拔。&#xff09; 1.3 我…

智能优化算法应用:基于缎蓝园丁鸟算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于缎蓝园丁鸟算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于缎蓝园丁鸟算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.缎蓝园丁鸟算法4.实验参数设定5.算法结果…

WIN10 x86环境部署ARM虚拟机(银河麒麟)

我们经常使用的是x86架构的cpu&#xff0c;而对于不同cpu架构的arm架构的操作系统&#xff0c;我们可以通过QEMU模拟器来进行模拟一个arm环境 1、部署前的准备 arm的镜像&#xff1a; 以此镜像为例&#xff1a;Kylin-Server-10-SP2-aarch64-Release-Build09-20210524.iso QE…

每日一练【移动零】

一、题目描述 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 二、题目解析 可以…

docker限制容器内存的方法

在服务器中使用 docker 时&#xff0c;如果不对 docker 的可调用内存进行限制&#xff0c;当 docker 内的程序出现不可预测的问题时&#xff0c;就很有可能因为内存爆炸导致服务器主机的瘫痪。而对 docker 进行限制后&#xff0c;可以将瘫痪范围控制在 docker 内。 因此&#…