leetCode动态规划“不同路径II”

迷宫问题是比较经典的算法问题,一般可以用动态规划、回溯等方法进行解题,这道题目是我昨晚不同路径这道题趁热打铁继续做的,思路与原题差不多,只是有需要注意细节的地方,那么话不多说,直接上coding和解析!

题目描述

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

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

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

网格中的障碍物和空位置分别用 1 和 0 来表示。
在这里插入图片描述

解析

如果做过类似迷宫问题的读者,对于这道题目的思路想必也会第一时间想到仍然使用动态规划的思路去解答,但是对于路径中的障碍物在这里却需要着重的单独讨论,因为有了障碍物,那么对于部分目标点的路径数会发生改变。此题目中需要考虑的特殊位置有如下图所示;
在这里插入图片描述
所画图给出了一种情况下的各个点下的路径数,可以看到,对于紫色笔给出的新的当前的节点路径数,仍满足原始状态下的dp[i][j] = dp[i-1][j]+dp[i][j-1]的动态递推式(但对于有障碍的节点不满足,那么障碍节点可达到路径数直接为0),对于迷宫问题,当前节点的可通行路线是由当前节点的左侧节点和正上方节点的可通过路径数相加得到,那对于左上方存在障碍的情况,当前节点的可通过数就需要变化。如下图所示。
在这里插入图片描述
这是相对于原始题目的第一处变化,考虑了障碍物,那么就得讨论一下障碍物在某些特殊位置下的特殊情况,比如障碍物在初始行、列上的时候,比如:
在这里插入图片描述
这种情况下,我们就不能单纯的只能把障碍物所处的位置上的路径数置为0,而是要把往后的那一列/一行上的数据都要置为0,为什么,因为机器人只能向下或者向右走,所以,对于初始行、列上的障碍物往后的点,机器人是无法到达的!!!
当然,还剩下最后一个情况,起点就有障碍物,那直接return 0咯~

代码

1.初始化dp数组

//初始化dp数组,我这里全给的-1,方便后续判别障碍物、无障碍物和路径数
int dp[110][110];for(int i=0;i<110;i++){for(int j =0;j<110;j++){dp[i][j] = -1;}}

2.根据地图,将地图中障碍物所处对应的dp数组位置置路径数为0

for(int i=0;i<obstacleGrid.size();i++){for(int j=0;j<obstacleGrid[i].size();j++){if(i == 0 && j ==0){//起点是障碍物if(obstacleGrid[i][j] == 1){return 0;}}if(i == 0){//障碍物在初始行上if(obstacleGrid[i][j] == 1){for(int m = j;m<obstacleGrid[i].size();m++){dp[i][m] = 0;}}}if(j == 0){//障碍物在初始列上if(obstacleGrid[i][j] == 1){dp[i][j] = 0;for(int x = i+1;x<obstacleGrid.size();x++){dp[x][j] = 0;}}}else if(i != 0 && j!= 0){//障碍物不在特殊位置上,那直接对应位置dp设置为0即可if(obstacleGrid[i][j] == 1){dp[i][j] = 0;}}}}

3.计算dp数组

for(int i=0;i<obstacleGrid.size();i++){for(int j=0;j<obstacleGrid[i].size();j++){if(i == 0 || j == 0){if(dp[i][j] == -1){dp[i][j] = 1;}}if(i != 0 && j != 0){if(dp[i][j] != 0){dp[i][j] = dp[i-1][j] + dp[i][j-1];}}}}

4. 完整代码和结果

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {// 跟第一种情况是一样的,只是对于地图中有障碍物的地方,对应的dp数组置为1int dp[110][110];for(int i=0;i<110;i++){for(int j =0;j<110;j++){dp[i][j] = -1;}}for(int i=0;i<obstacleGrid.size();i++){for(int j=0;j<obstacleGrid[i].size();j++){if(i == 0 && j ==0){if(obstacleGrid[i][j] == 1){return 0;}}if(i == 0){if(obstacleGrid[i][j] == 1){for(int m = j;m<obstacleGrid[i].size();m++){dp[i][m] = 0;}// break;}}if(j == 0){if(obstacleGrid[i][j] == 1){dp[i][j] = 0;for(int x = i+1;x<obstacleGrid.size();x++){dp[x][j] = 0;}// break;}}else if(i != 0 && j!= 0){if(obstacleGrid[i][j] == 1){dp[i][j] = 0;}}}}for(int i=0;i<obstacleGrid.size();i++){for(int j=0;j<obstacleGrid[i].size();j++){if(i == 0 || j == 0){if(dp[i][j] == -1){dp[i][j] = 1;}}if(i != 0 && j != 0){if(dp[i][j] != 0){dp[i][j] = dp[i-1][j] + dp[i][j-1];}}// else{//     dp[i][j] = dp[i-1][j] + dp[i][j-1];// }}}cout<<dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1];return dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1];}
};

在这里插入图片描述

总结

个人感觉,这类题目是十分具有代表性的动态规划算法题 ,为什么这么说,因为动态规划要满足最优子结构,而恰恰这类题的子结构十分清晰,就比如我要知道当前位置有几种路径可以到达,就可以直接从我的前一步,也就是我的左边那一步和正上面的那一步就能到达,也就是我的左边和上面是与我当前可联通的,那么就直接得到了我当前的可通行路径数。有的人可能会说,那这样的话,应该是两者之和再加1才是最终的路径数呀?
其实不然,我最开始也陷入了这样的思维模式中去了,而其实应该这么想,我们所要求的是路径,而不是步数,讨论的不是走了几步,而是有几种到达的方法,换言之就是,只要我能到达左边那个位置或者上面那个位置,那么我一定能够到达当前所求的这个位置,那么也就说明,到达上面/左边位置的路径均能到达我当前的位置,那么两个地方的路径数之和就是到达当前位置的路径数之和~ 这里就不贴图了 ,如果文字描述不清楚,可以结合上面的xyz那张图(也就是所有图中的第三张图)进行结合理解。
动态规划变种很多,前些时候做了些公司面试笔试题 ,发现很多题可以用动态规划来做,但是不得其解,文中的题目是比较清晰的,容易推出动态规划递推式的类型,对于一些变种,还需要多做多总结!欢迎各位读者在评论区进行讨论,有更好的方法我也很愿意与您交流学习!
如果文章对您有帮助,可以点个小赞哦~

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

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

相关文章

2023年7月京东投影仪行业品牌销售排行榜(京东大数据)

鲸参谋监测的京东平台7月份投影仪行业销售数据已出炉&#xff01; 7月份&#xff0c;投影仪市场呈现增长趋势。根据鲸参谋平台的数据可知&#xff0c;7月京东平台投影仪的销量将近20万&#xff0c;同比增长约16%&#xff1b;销售额将近3.8亿&#xff0c;同比增长约4%。 ​*数据…

uni-app 之 v-on:click点击事件

uni-app 之 v-on:click点击事件 image.png <template><!-- vue2的<template>里必须要有一个盒子&#xff0c;不能有两个&#xff0c;这里的盒子就是 view--><view>--- v-on:click点击事件 ---<view v-on:click"onclick">{{title}}<…

Visual Studio 新建类从默认internal改为public

前言 之前一直用的Resharp辅助编写C#代码&#xff0c;Resharp用起来的确方便不少&#xff0c;但是太消耗开发机内存了。重装电脑后&#xff0c;还是决定使用Visual Studio内置的功能。 默认情况下&#xff0c;Visual Studio 中生成一个类或接口是internal类型的&#xff0c;而…

打造西南交通感知新范式,闪马智能携手首讯科技落地创新中心

9月4日&#xff0c;2023年中国国际智能产业博览会&#xff08;以下简称“智博会”&#xff09;在重庆拉开帷幕。大会期间&#xff0c;由上海闪马智能科技有限公司&#xff08;以下简称“闪马智能”&#xff09;与重庆首讯科技股份有限公司&#xff08;以下简称“首讯科技”&…

什么是安全运营中心(SOC),应该了解什么

安全运营中心&#xff08;SOC&#xff09; 是一种企业监视和警报设施&#xff0c;可帮助组织检测安全威胁、监视安全事件和分析性能数据以改进公司运营。 什么是安全运营中心&#xff08;SOC&#xff09; 安全运营中心&#xff08;SOC&#xff09;是一个中央监视和监视中心&a…

Spring AOP与静态代理/动态代理

文章目录 一、代理模式静态代理动态代理代理模式与AOP 二、Spring AOPSping AOP用来处理什么场景jdk 动态代理cglib 动态代理面试题&#xff1a;讲讲Spring AOP的原理与执行流程 总结 一、代理模式 代理模式是一种结构型设计模式&#xff0c;它允许对象提供替代品或占位符&…

macos 不支持svn安装

macos 10.13可能不支持svn命令,所以要安装 xcode-select --install 弹窗在线安装失败的话只能手动下载安装 打开:Sign In - Apple 搜索Command Line Tools (macOS 10.13) 下载9.4.1版本直接安装后即可

Docker实战:docker compose 搭建Rocketmq

1、配置文件准备 1.1、 新建目录&#xff1a;/home/docker/data/rocketmq/conf mkdir /home/docker/data/rocketmq/conf1.2、 在上面目录下新建文件broker.conf文件&#xff0c;内容如下 brokerClusterName DefaultCluster brokerName broker-a brokerId 0 deleteWhen 0…

【算法】分治法的应用——棋盘覆盖问题

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法分析与设计知识专栏&#xff1a;算法分析&#x1f525; 给大家跳…

华为数通方向HCIP-DataCom H12-821题库(单选题:181-200)

第181题 某管理员需要创建AS Path过滤器(ip as-path-iter),允许AS_Path中包含65001的路由通过,那么以下哪一项配置是正确的? A、​​ip as-path-filter 1 permit 65001​​ B、​​ip as-path-filter 1 permit "65001​​ C、​​ip as-path-filter 1 permit *6500…

OC和Swift混编,导入头文件‘xxx-Swift.h‘ file not found

在OC的项目里加入Swift代码&#xff0c;创建完桥接文件后&#xff0c;需要倒入Swift头文件&#xff0c;头文件的格式为“项目名-Swift.h”。 如下图&#xff0c;我在Xcode上看到我的项目名为YichangPark&#xff0c;导入 #import "YiChangPark-Swift.h" 之后提示 “Y…

【笔记】软件测试的艺术

软件测试的心理学和经济学 测试是为发现错误而执行程序的过程&#xff0c;所以它是一个破坏性的过程&#xff0c;测试是一个“施虐”的过程。 软件测试的10大原则 1、测试用例需要对预期输出的结果有明确的定义 做这件事的前提是能够提前知晓需求和效果图&#xff0c;如果不…