不同路径

111 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

路径问题容易可视化,我们可以观察动态规划的转移过程了解到最佳路径是如何被选择

题目描述

一个机器人位于一个 m x n 网格的左上角,机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。问总共有多少条不同的路径?

image.png

思路分析

由于只能向下或者向右走,那么当前的路径数=上面节点的路径数+左面节点的路径数,定义二维数组dp[i][j]记录各节点到起点的路径数

  1. 只能向右走时:dp[i][j]=dp[i][j-1]
  2. 只能向下走时: dp[i][j]=dp[i-1][j]
  3. 既能向右又能向下时:dp[i][j]=dp[i][j-1]+dp[i-1][j]

代码实现

  class Solution {
public:
    int uniquePaths(int m, int n) {
        //当i=m-1时(最后一行),不能向下
        //当j=n-1时(最后一列),不能向右
        //dp[i][j]代表从初始节点到当前节点的路径数
        //dp[i][i]=初始节点到当前节点所在行的前一个节点的路径数+初始节点到当前节点所在列的前一个节点的路径数
        vector<vector<int>> dp(m, vector<int>(n, 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];
    }
};

不同路径题目变式,即有障碍物时

同上一题,当考虑网格中有障碍物,应如何计算路径数?网格数组中,有障碍物值为1,没有障碍物值为0.

思路分析

此时要进行情况分析;

  1. 起点和终点只要有一个有障碍物,就没有从起点到终点的路径数
  2. 在网格中访问时,分为四种情况:
    • 访问起点(此时进行路径数目初始化)
    • 访问第一列和第一行以外的节点,此时路径数目能访问节点左侧+上侧
    • 访问第一列的节点,此时路径数目只能访问上侧
    • 访问第一行的节点,此时路径数目只能访问左侧
  3. 在访问某节点时分为当前节点有障碍物和没有障碍物两种情况

代码描述

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        //获取表格的行和列
        int row=obstacleGrid.size(),col=obstacleGrid[0].size();
        //定义一个二维数组存储初始节点到此节点的路径数目
        vector<vector<int>> dp(row, vector<int>(col, 1));
        //判断起点和终点是否有障碍物,只要有一个有障碍物,就不能从起点到达终点
        if(obstacleGrid[0][0]==1||obstacleGrid[row-1][col-1]==1) return 0;
        //当起点和终点都没有障碍物时(因为起点和终点只要有障碍物就会在上面的语句中返回,不会进行到这一步)
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++)
            {
                //给第一个节点初始化,只有一个节点时路径数是1
                if(i==0&&j==0) dp[i][j]=1;
                //因为if...else if..片段中只能执行一个语句,此时代表i>0||j>0
                //当前节点有障碍物,因为此点不能过,则当前节点的路径数=0
                else if(obstacleGrid[i][j]==1) dp[i][j]=0;
                //此时(i>0||j>0)&&当前节点没有障碍物
                //当不是第一列和第一行时
                else if(i>0&&j>0) dp[i][j]=dp[i][j-1]+dp[i-1][j];
                //此时不是第一行,但是是第一列,此时只能加上面一节点的路径数
                else if(i>0)
                    dp[i][j]=dp[i-1][j];
                //第一行,但是不是第一列,此时只能加上左边的路径数
                else if(j>0)
                    dp[i][j]=dp[i][j-1];
                }
            }
            //输出终点的路径数即可
        return dp[row-1][col-1];
    }
};