题目:
设想有个机器人坐在一个网格的左上角,网格 r 行 c 列。机器人只能向下或向右移动,但不能走到一些被禁止的网格(有障碍物)。设计一种算法,寻找机器人从左上角移动到右下角的路径。
示例:
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: [[0,0],[0,1],[0,2],[1,2],[2,2]]
解释:
输入中标粗的位置即为输出表示的路径,即
0行0列(左上角) -> 0行1列 -> 0行2列 -> 1行2列 -> 2行2列(右下角)
解题思路:动态规划
1.先找到可行的路径,不可达的坐标点 dp=0
2.如果终点的dp不为0,说明存在可达的路径
3.那么就从终点往回走,找到可以到达起点的路径,每走一步都要将坐标添加到res数组中
4.由于是从后往前的,所以要将res进行反转
源代码如下:文章来源地址https://www.toymoban.com/news/detail-659156.html
class Solution {
public:
vector<vector<int>> pathWithObstacles(vector<vector<int>>& obstacleGrid) {
vector<vector<int>> res;
if(obstacleGrid.size()==0) return res;//矩阵为空,直接返回空数组
int m=obstacleGrid.size();
int n=obstacleGrid[0].size();
//矩阵的起点和终点不可达,则返回空数组
if(obstacleGrid[0][0]==1||obstacleGrid[m-1][n-1]==1) return res;
int dp[m][n];//定义动态规划数组
dp[0][0]=1;//起点位置可达,置为1
//先找第一列的元素是否可达
for(int i=1;i<m;i++)
{
//不可达,dp置为0
if(obstacleGrid[i][0]==1) dp[i][0]=0;
//可达,则dp等于上一行的
else
{
dp[i][0]=dp[i-1][0];
}
}
//找第一行的元素
for(int i=1;i<n;i++)
{
if(obstacleGrid[0][i]==1) dp[0][i]=0;
else
{
dp[0][i]=dp[0][i-1];
}
}
//其他剩余元素
for(int i=1;i<m;i++)
{
for(int j=1;j<n;j++)
{
if(obstacleGrid[i][j]==1) dp[i][j]=0;
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
//如果终点的dp=0,说明不能到达终点,则返回空数组
if(dp[m-1][n-1]==0) return res;
//以下情况是已经找到路径了,只需要把路径添加到res中
//从后往前找可以到达的点
int i=m-1,j=n-1;
while(i!=0||j!=0)
{
res.push_back({i,j});
//往上走
int up=0;
if(i>0) up=dp[i-1][j];
//往左走
int left=0;
if(j>0) left=dp[i][j-1];
//哪个dp值不为0,则走哪个方向
if(up>=left) i--;
else j--;
}
//最后把起点添加到数组中
res.push_back({0,0});
//再将数组翻转,就是正确顺序了
reverse(res.begin(),res.end());
return res;
}
};
解题思路:回溯
需要注意的是,要添加一个访问数组,标记该坐标是否已经被访问过。详解看代码文章来源:https://www.toymoban.com/news/detail-659156.html
源代码如下:
class Solution {
public:
bool isfind=false;//是否已经找到路径
void dfs(vector<vector<int>>& obstacleGrid,vector<vector<int>>& res,vector<vector<bool>>& visited,int m,int n,int i,int j)
{
//如果下标i和j越界
//如果已经找到路径(isfind==true)
//如果当前坐标有障碍物
//如果当前坐标已访问
//遇到以上这些情况 直接返回
if(i<0||i>=m||j<0||j>=n||isfind||obstacleGrid[i][j]==1||visited[i][j]) return;
//当前坐标已经到达终点,说明找到路径了
if(i==m-1&&j==n-1)
{
isfind=true;//isfind置为真
res.push_back({i,j});//将终点添加到数组中
//并返回
return;
}
//其余正常情况,每遍历一个坐标,就将该坐标标记为已访问
visited[i][j]=true;
res.push_back({i,j});//坐标添加到数组中
//递归,往下走
dfs(obstacleGrid,res,visited,m,n,i+1,j);
//递归,往右走
dfs(obstacleGrid,res,visited,m,n,i,j+1);
//回溯
if(!isfind) res.pop_back();
}
vector<vector<int>> pathWithObstacles(vector<vector<int>>& obstacleGrid) {
vector<vector<int>> res;
int m=obstacleGrid.size();
int n=obstacleGrid[0].size();
if(obstacleGrid.size()==0) return res;
//标记当前坐标是否已经访问过,初始值都为false
vector<vector<bool>> visited(m, vector<bool>(n, false));
if(obstacleGrid[0][0]==1||obstacleGrid[m-1][n-1]==1) return res;
dfs(obstacleGrid,res,visited,m,n,0,0);
return res;
}
};
到了这里,关于迷路的机器人(递归回溯+动态规划两个方法实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!