不同路径II --动态规划
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
说明:m和n的值不超过100。
示例1:
输入: [ [0,0,0], [0,1,0], [0,0,0] ] 输出: 2 解释: 3x3 网格的正中间有一个障碍物。 从左上角到右下角一共有 2 条不同的路径: 1. 向右 -> 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 -> 向右
解法一: 动态规划
思想算法:
- 如果第一个格子点是obstacleGrid[0][0] 是 1, 说明有障碍物,那么机器人就不能做任何的移动,我们就直接返回0;
- 否则如果obstacleGrid[0][0] 是 0, 我们初始化这个值为1,然后继续算法;
- 遍历第一行,如果有个格子是为1,说明当前节点有障碍物,没有路径可走,设置为0;否则设这个值是前一个节点的值,如下:
let verticalValue = (obstacleGrid[0][i] == 0 && dp[0][i - 1] == 1) ? 1 : 0
dp[0].append(verticalValue)
- 遍历第一列,如果有一个格子初始值是1, 说明当前节点为障碍物,没有路径可以通过, 设置为0; 否则这个值为前一个节点的值
(dp[i-1][0]) == 0 || (obstacleGrid[i][0] == 1)判断为0或者1,加入进去
- 现在从obstacleGrid[1][1]开始遍历整个数组,如果某个个字初始化不包含任何障碍物,就把值赋予上方和左侧两个格子方案之和
let value = dp[i - 1][j] + dp[i][j - 1]
dp[i].append(value)
不包含障碍物上面.
6. 如果这个点是障碍物设置为0, 保证对后面的路径不产生贡献.
代码如下
func uniquePathsWithObstacles(_ obstacleGrid: [[Int]]) -> Int { guard obstacleGrid.count > 0 else {return -1} let rowLength = obstacleGrid.count //显示多少行 let verticalLength = obstacleGrid[0].count //显示多少列 var dp = [[Int]]() if obstacleGrid[0][0] == 1 {//1代表有障碍 return 0 } //初始化第一个元素,也就是dp[0][0] var rowArr = [Int]() for i in 0..<rowLength { if i == 0 { for j in 0..<verticalLength { if j == 0 { rowArr.append(1) } } } } dp.append(rowArr) //初始化第一列 for i in 1..<rowLength { var vertical = [Int]() let rowValue = (obstacleGrid[i][0] == 0 && dp[i-1][0] == 1) ? 1 : 0 for j in 0..<verticalLength { if j == 0 { vertical.append(rowValue) } } dp.append(vertical) } //初始化第一行 for i in 1..<verticalLength { let verticalValue = (obstacleGrid[0][i] == 0 && dp[0][i - 1] == 1) ? 1 : 0 dp[0].append(verticalValue) } //初始化其它元素 for i in 1..<rowLength { for j in 1..<verticalLength { if obstacleGrid[i][j] == 0 { let value = dp[i - 1][j] + dp[i][j - 1] dp[i].append(value) } else { dp[i].append(0) } } } return dp[rowLength-1][verticalLength-1] }
上面运行代码如下:
上面就是不同路径关于动态规划下,swift完整代码,可以直接运行出来,代码也有注释,以后有新的解法,会持续更新,希望对大家有所帮助!!!