不同路径|
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?

解法(动态规划)
1. 状态表示:
对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式:i. 从 [i, j] 位置出发,巴拉巴拉;ii. 从起始位置出发,到达 [i, j] 位置,巴拉巴拉。这⾥选择第⼆种定义状态表⽰的⽅式:dp[i][j] 表⽰:⾛到 [i, j] 位置处,⼀共有多少种⽅式。
2. 状态转移⽅程:
 简单分析⼀下。如果  dp[i][j]  表⽰到达  [i, j]  位置的⽅法数,那么到达  [i, j]  位置之 前的⼀⼩步, 
 
 有两种情况:  
 
 
 i.  从  [i, j]  位置的上⽅(  [i - 1, j]  的位置)向下⾛⼀步,转移到  [i, j]  位置;  
 
 
 ii.  从  [i, j]  位置的左⽅(  [i, j - 1]  的位置)向右⾛⼀步,转移到  [i, j]  位置。  
 
 
 由于我们要求的是有多少种⽅法,因此状态转移⽅程就呼之欲出了:  dp[i][j] = dp[i - 1]  
 
 [j] + dp[i][j - 1]  。  
 
 
3. 初始化:
 可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:  
 
 
 i.  辅助结点⾥⾯的值要「保证后续填表是正确的」;  
 
 
 ii.  「下标的映射关系」。  
 
 
 在本题中,「添加⼀⾏」,并且「添加⼀列」后,只需将  dp[0][1]  的位置初始化为  1  即可。 
 
 
 
4. 填表顺序:
 根据「状态转移⽅程」的推导来看,填表的顺序就是「从上往下」填每⼀⾏,在填写每⼀⾏的时候  
  「从左往右」。  
  5. 返回值:
 根据「状态表⽰」,我们要返回  dp[m][n]  的值。  
  class Solution {public int uniquePaths(int m, int n) {int[][] dp = new int[m + 1][n + 1];dp[0][1] = 1;for(int i = 1; i <= m; i++) // 从上往下每⼀⾏for(int j = 1; j <= n; j++) // 从左往右填写每⼀⾏dp[i][j] = dp[i - 1][j] + dp[i][j - 1];return dp[m][n];}
}不同路径||
解法(动态规划)
 ⼀个机器⼈位于⼀个 m x n ⽹格的左上⻆ (起始点在下图中标记为 “Start” )。  
  机器⼈每次只能向下或者向右移动⼀步。机器⼈试图达到⽹格的右下⻆(在下图中标记为  
  “Finish”)。  
  现在考虑⽹格中有障碍物。那么从左上⻆到右下⻆将会有多少条不同的路径?  
  ⽹格中的障碍物和空位置分别⽤ 1 和 0 来表⽰。  
  和上题差不多,只需要注意 障碍物即可。 
 到达 [i, j] 位置之前的⼀⼩步,有两种情况:i. 从 [i, j] 位置的上⽅( [i - 1, j] 的位置)向下⾛⼀步,转移到 [i, j] 位置;ii. 从 [i, j] 位置的左⽅( [i, j - 1] 的位置)向右⾛⼀步,转移到 [i, j] 位置。但是, [i - 1, j] 与 [i, j - 1] 位置都是可能有障碍的,此时从上⾯或者左边是不可能到达 [i, j] 位置的,也就是说,此时的⽅法数应该是 0。由此我们可以得出⼀个结论,只要这个位置上「有障碍物」,那么我们就不需要计算这个位置上的值,直接让它等于 0 即可。
int uniquePathsWithObstacles(vector<vector<int>>& ob) {// 1. 创建 dp 表// 2. 初始化// 3. 填表// 4. 返回值int m = ob.size(), n = ob[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 1));dp[0][1] = 1;for(int i = 1; i <= m; i++)for(int j = 1; j <= n; j++)if(ob[i - 1][j - 1] == 0)dp[i][j] = dp[i - 1][j] + dp[i][j - 1];return dp[m][n];}