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).How many possible unique paths are there?
这题是典型的dynamic programming题,但我一开始的第一反应是直接递归最方便,因为高中数学归纳法的影响吧。这种问题都可以递归来做。对于坐标[m,n]的点,到达他的所有可能路线一定等于到达[m-1,n]和 到达[m,n-1]的所有路线数目和和,因为要想到达[m,n]最后必须是经过这两个点,所以代码简明如下:
方法一:递归(回溯)
int uniquePaths(int m, int n) {
if (m == 0 || n == 0) return 0;
if (m == 1 || n == 1) return 1;
return uniquePaths(m-1, n) + uniquePaths(m, n-1);
}
计算上这样做是对的,可是这题超时了。时间效率上比较低。
方法二:动态规划
思想上跟之前的回溯一样,每一个位置可以从它的左边和上边的路径数得到,所以我们可以从起点到终点建立一个矩阵来记录这些值。相比于第一种递归,少了从后往前再从前往后的过程,也少了运行时调用函数的过程。
int uniquePaths(int m, int n) {
vector<vector<int>> res(m, vector<int>(n,1));
int i, j;
for (i = 1; i < m; i++) {
for (j = 1; j < n; j++) {
res[i][j] = res[i-1][j] + res[i][j-1];
}
}
return res[m-1][n-1];
}
方法三:公式法
其实这个问题就是个排列组合的问题,假设是3x7的矩阵,其实到终点就是向下走两步加上向右走6步,一共8步,有多少种排列组合。8个选2或者选6的问题。
int uniquePaths(int m, int n) {
int tm = min(m,n) - 1;
int tn = max(m,n) - 1;
int t = tm + tn;
int i;
double res = 1;
// here we calculate the total possible path number
// Combination(N, k) = n! / (k!(n - k)!)
// reduce the numerator and denominator and get
// C = ( (n - k + 1) * (n - k + 2) * ... * n ) / k!
for (i = 1; i <= tm; i++) {
res = res * (t--) / i;
}
return res;
}
直接描述这个公式就行了。特别注意的一个问题,因为我们不是先算分母再算分子,我们是每次乘一个又除一个,所以res得是double,否则作为int,很多时候会有小数导致res结果不对,返回答案错误,千万注意。