一道经典的动态规划题,题面如下:
机器人要从左上角走到MxN的网格的右下角,每次只能向左和向右走,m n均小于100,问路径总数。解法如下:
/*递推法解动态规划一般分为以下几步,个人经验*/
/*1.明确DP数组的含义:DP[m][n]表示从原点(0, 0)出发,到(m,n)的路径总数*/
/*2.递推奠基:明确那些已经明确答案的数组元素,将它们在递推前初始化*/
/*3.递推:找到递推规律,迭代求解非奠基部分的答案*/
/*下面的代码就是按照这个顺序来写的*/
int uniquePaths(int m, int n) {
/*1.DP[m][n] stores the total number of paths to (m,n)*/
int DP [100][100] = {
0};
/*2.set the foundation of recursion*/
for(int i = 0 ; i < m || i < n ; ++i)
DP[i][0] = DP[0][i] = 1;
/*3.recursion process*/
for(int i = 1 ; i < m ; ++i)
for(int j = 1 ; j < n ; ++j)
DP[i][j] = DP[i][j - 1] + DP[i - 1][j];
return DP[m - 1][n - 1];
}
这道题紧跟着有一道变种,就是在网格中放上障碍物,放上障碍物的格子不可以走。这会对递推奠基和递推过程的逻辑造成一定的影响,也就是对于奠基部分,石头向右和向下的均无法到达,对于递推部分,如果走到石头处,路径数完全清0表示此路不通。
还是按照3部曲,但是要在每一部分修改一些逻辑:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
/*1.DP[m][n] means the total number of paths from (0, 0) to (m, n)*/
int DP[100][100] = {
0};
/*extract the value of m & n*/
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
/*2.set the foundation of recursion*/
for(int i = 0 ; i < m ; ++i)
if(!obstacleGrid[i][0])
DP[i][0] = 1;
else break;
for(int j = 0 ; j < n ; ++j)
if(!obstacleGrid[0][j])
DP[0][j] = 1;
else break;
/*3.recursive process*/
for(int i = 1 ; i < m ; ++i)
for(int j = 1 ; j < n ; ++j)
DP[i][j] = obstacleGrid[i][j] == 1 ? 0 : DP[i - 1][j] + DP[i][j - 1];
return DP[m - 1][n - 1];
}