算法设计与分析(十)

63. Unique Paths II

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

Now consider if some obstacles are added to the grids. How many unique paths would there be?
maze
An obstacle and empty space is marked as 1 and 0 respectively in the grid.

Example

Input:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:

  1. Right -> Right -> Down -> Down
  2. Down -> Down -> Right -> Right

Note

m and n will be at most 100.

思路

这是一道比较特别的迷宫类型题,起点跟终点固定在两个角,行走的方向只能往下或者往右。那么每个坐标的状态只能从上、左两个坐标的状态得到,这很符合动态规划的特点,于是我就朝着这个方向去考虑了。

问题就是每个坐标的状态代表什么了。既然题目是求起点到终点的可到达路径数目,如果坐标状态表示目前到这个坐标有多少条路径,它应该是上、右两个坐标可到达路径数目的和,而不是两者的较小值或者较大值。所以我们能得到状态转移方程:

path[i][j] = path[i - 1][j] + path[i][j - 1];

因为迷宫是有边界的,存在越界的问题,当一个坐标的上坐标或者右坐标在迷宫外时,它的可到达路径数目显然是0,因此新的状态转移方程是:

top = (i - 1 >= 0) ? path[i - 1][j] : 0;
left = (j - 1 >= 0) ? path[i][j - 1] : 0;
path[i][j] = top + left;

最后要解决的就是初始化的问题。起点path[0][0]的值肯定不能为0,不然后面的坐标不管怎么算也是0了。所以把起点坐标的状态值设为1,表示我们一开始就站在起点,起点的可到达路径数目自然为1。然后提交上去时会发现这道题目有个特殊样例如下图所示:

Input:
[
[ 1 ]
]

表示整个迷宫只有一个点,起点跟终点是同一个坐标,而且这个坐标上还有障碍物,所以这个样例的输出是0。感觉这个样例就是想考一下做题人的考虑够不够全面,是否针对特殊情况制定了策略,跟动态规划的运用没什么关系。显然我就是没考虑到这种特殊情况,不然也不会发现这个样例。解决办法也很简单啦,在进行状态转移方程的计算前判断一下起点上有没有障碍物就可以了,关于这道题的思考过程就讲完了,完整的代码在下面给出。

代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) 
    {
      int top = 0;
      int left = 0;

      vector<vector<int>> path(obstacleGrid.size());
      for (int i = 0; i < path.size(); i++)
        path[i].resize(obstacleGrid[0].size());

      //如果起点有障碍物,那么可到达路径就为0
      if (obstacleGrid[0][0] == 1) path[0][0] = 0;
      else path[0][0] = 1;

      for (int i = 0; i < obstacleGrid.size(); i++)
        for (int j = 0; j < obstacleGrid[0].size(); j++)
          {
            if (i == 0 && j == 0) continue; //跳过path[0][0]的赋值
            if (obstacleGrid[i][j] == 1)
            {
              path[i][j] = 0; //有障碍物的坐标可到达路径均为0
            }
            else //obstacleGrid[i][j] == 0
            {
              //处理越界问题
              top = (i - 1 >= 0) ? path[i - 1][j] : 0;
              left = (j - 1 >= 0) ? path[i][j - 1] : 0;
              path[i][j] = top + left;
            }
          }

      return path[obstacleGrid.size() - 1][obstacleGrid[0].size() - 1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值