参考文章:http://www.leetcode.com/2010/11/unique-paths.html
题目描述:给定一个m×n的方格,求方格(1,1)到点(m,n)的路径条数。路径只能向右或向下走。
文章中给出了三种算法:
算法1:最容易想到的也是最原始的回溯搜索算法,递归实现回溯。
算法2:由于在1回溯过程中,会做很多次重复计算。为了减少重复计算,使用动态规划中的备忘录算法,将已经计算出的值保存在数组中,使用这些值计算新的值。
算法3:自底向上的动态规划算法,也是最简洁的算法。
数学公式:高中排列组合的一道题,C(m+n-2,m-1)=C(m+n-2,n-1)
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cassert> 3 4 using namespace std; 5 6 //纯粹的回溯算法 7 int backtrack(int r,int c,int m,int n) 8 { 9 if (r==m && c==n) 10 { 11 return 1; 12 } 13 if (r>m || c>n) 14 { 15 return 0; 16 } 17 return backtrack(r+1,c,m,n)+backtrack(r,c+1,m,n); 18 } 19 20 const int M_MAX=100; 21 const int N_MAX=100; 22 //使用dp备忘录改进回溯算法,减少重复计算 23 int dpbacktrack(int r,int c,int m,int n,int mat[][N_MAX+2]) 24 { 25 if (r==m && c==n) 26 { 27 return 1; 28 } 29 if (r>m || c>n) 30 { 31 return 0; 32 } 33 if (mat[r+1][c]==-1) //等于-1说明还没有计算过 34 { 35 mat[r+1][c]=dpbacktrack(r+1,c,m,n,mat); 36 } 37 if (mat[r][c+1]==-1) 38 { 39 mat[r][c+1]=dpbacktrack(r,c+1,m,n,mat); 40 } 41 return mat[r+1][c]+mat[r][c+1]; 42 } 43 44 int bt(int m,int n) 45 { 46 int mat[M_MAX+2][N_MAX+2]; 47 for (int i=0;i<M_MAX+2;i++) 48 { 49 for (int j=0;j<N_MAX+2;j++) 50 { 51 mat[i][j]=-1; 52 } 53 } 54 return dpbacktrack(1,1,m,n,mat); 55 } 56 57 //自底向上的dp算法 58 int dp(int m,int n) 59 { 60 int mat[M_MAX+2][N_MAX+2]={0}; 61 mat[m][n+1]=1; 62 for (int r=m;r>=1;r--) 63 { 64 for (int c=n;c>=1;c--) 65 { 66 mat[r][c]=mat[r+1][c]+mat[r][c+1]; 67 } 68 } 69 return mat[1][1]; 70 } 71 72 int main() 73 { 74 int m=7; 75 int n=4; 76 cout<<dp(m,n)<<endl; 77 cout<<bt(m,n)<<endl; 78 cout<<backtrack(1,1,m,n)<<endl; 79 return 0; 80 }