题目:
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?
解法:这题有两种想法,第一种:利用排列组合的思想,从左上角移动到右下角需要向下移动m-1步,向右移动n-1部,因此总共有C(m+n-2, m-1)种移动方法。
换而言之就是求C(n,k),求的方法肯定不能先算n!再算k!和(n-k)!,因为在100的限定下肯定会超出int的范围,这里需要利用C(n,k)=C(n-1,k-1)+C(n-1,k-1)的递推关系,以及边界条件C(n,0) = C(n,n) = 1。
用递归肯定会有许多重复的计算,这是典型的动态规划(DP)算法,用一张n*k的表result来存储C(n,k)的值,设好边界后依次求出所有值,最后返回result[n-1][k-1]即可。
第二种思路是考虑题目的物理意义。设从左上角到(i,j)的路径为f(i, j),那么它前一步所在的位置只有两种可能(i,j-1)以及(i-1, j)。所以有f(i, j)=f(i-1,j)+f(i, j-1)。当然边界处特殊处理。
下面给出第一种思路的代码,第二种思路可以见Unique Paths II。
public class No61_UniquePaths {
public static void main(String[] args){
System.out.println(uniquePaths(51, 9));
}
public static int uniquePaths(int m, int n) {
if(m == 1 || n == 1) return 1;
return C(m+n-2,m-1);
}
public static int C(int n, int k){
// TLE...应该采用动态规划(DP)算法
// if(k == 0 || k == n) return 1;
// if(k == 1) return n;
// return C(n-1, k) + C(n-1, k-1);
int[][] result = new int[n+1][k+1];
for(int i=1;i<n+1;i++){
int col = i<k?i:k;
for(int j=0;j<=col;j++){
if(j == 0 || j == i) result[i][j] = 1;
else{
result[i][j] = result[i-1][j-1] + result[i-1][j];
}
}
}
return result[n][k];
}
}