题目描述
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
说明:m 和 n 的值均不超过 100。
样例
输入: m = 3, n = 2 输出: 3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下 -> 向右 3. 向下 -> 向右 -> 向右
输入: m = 7, n = 3 输出: 28
思路分析
方法一:典型的动态规划问题
即每一步要记录当前的可能数
-
初始状态
-
当前这个状态只和左边和上边的格子有关系.
-
依次求解
所以可以得出状态方程
dp[i][j] = dp[i-1][j] + dp[i][j-1]
方法二:对方法一进行优化,因为实际记录值只需要dp[j]的值,i只是记录行数,把二维数组优化为一维数组
dp[j] = dp[j] + dp[j-1]
方法三:排列组合 因为无论怎么走,向右和向下的步数是固定的,可以用c(m-1,m+n-2)直接得出答案
代码及结果
方法一:
public int uniquePaths(int m, int n) {
if (m<0 || n<0 || m>100 || n>100) {
return 0;
}
int dp[][] = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i==0 || j==0) {
dp[i][j] = 1;
}
else {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
方法二:
public int uniquePaths(int m, int n) {
if (m<0 || n<0 || m>100 || n>100) {
return 0;
}
int dp[] = new int[n];
dp[0] = 1;
for (int i = 0; i < m; i++) {
for (int j = 1; j < n; j++) {//第一列永远唯一 所以从第二列加起
dp[j] = dp[j] + dp[j-1];
}
}
return dp[n-1];
}
方法三:
public static int uniquePaths(int m, int n) {
if (m<0 || n<0 || m>100 || n>100) {
return 0;
}
long small = m<n ? m-1 : n-1;
long big = m<n ? n-1 : m-1;
double top = 1; //c(3,9) 3为top 9为bottom
double bottom = 1;
for (int i = 1; i <= small; i++) {
top *= i;
bottom *= big + small + 1 -i; //从1开始算起 从后往前少算一位 所以+1
}
return (int) (bottom/top);
}