一、前言
参考文献:代码随想录
今天主要的题目是动态规划的路径问题,动态规划五要点;
1、确定dp数组,dp[i]代表什么i代表什么;
2、递推公式;
3、初始化dp数组;
4、遍历顺序;
5、打印dp数组;
二、不同路径
1、思路:
我感觉动态规划,我听的很认真,然后这个题目,我有一点感觉,但是我又想不出来,只好去求看一下卡哥,但是才看了三分钟,我就想到思路了。。。
(1)dp数组,由于这是一个二维图,所以需要创建一个二维的dp数组,i,j分别代表一个点位,dp[i][j]代表到达该点的位置;
(2)初始化:我们发现,机器人只允许向右或者向下移动,所以在[i][0]上面的情况全是1,以及[0][j]也全是1,所以这就是初始化;
(3)递推公式:
当我把图画出来后不难发现当需要拐弯时,那个结点的情况就是上面的路径加上左边的路径;
(图很潦草)但是也能看懂,所以递推公式就是:
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
(4)遍历顺序:很显然,我们是要慢慢的积累我们不同路径的数量,所以是从最小的地方开始,但是不是用上边界和左边界,而是从[1][1]的地方开始;
2、整体代码如下:
class Solution {
public:int uniquePaths(int m, int n) {// 1、定义dp数组,i,j表示位置,dp[i][j]表示到达结点的次序vector<vector<int>> dp(m, vector<int>(n));// 2、初始化dp数组for (int i = 0; i < m; i++) {dp[i][0] = 1;}for (int j = 0; j < n; j++) {dp[0][j] = 1;}// 3、遍历for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {// 4、递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}// 5、打印dp数组// for (int i = 0; i < m; i++) {// for (int j = 0; j < n; j++) {// cout << dp[i][j] << " ";// }// cout << endl;// }return dp[m - 1][n - 1];}
};
三、不同路径||
1、思路:
这个题目和上一个不同路径的题目思路差不多,但是其中多了障碍物,所以在递推公式上,我们就得分很多种情况,来做出不同的措施;
(1)dp数组,与上一个题目的作用相同;
(2)初始化,这里的初始化就有一些区别。因为在初始化上边界和左边界时可能会出现障碍物,一旦出现,就需要把后面的路径数设置为0:
for (int i = 0; i < m; i++) {if (obstacleGrid[i][0] == 1) {for (int j = i; j < m; j++) {dp[i][0] = 0;}break;}dp[i][0] = 1;}for (int j = 0; j < n; j++) {if (obstacleGrid[0][j] == 1) {for (int i = j; i < n; i++) {dp[0][j] = 0;}break;}dp[0][j] = 1;}
(3)递推公式:在递推公式中,我们需要做出以下几种情况的判断,
1、如果当前[i][j]位置有障碍物,则直接设置为0;
2、如果上方有障碍物,左边没有:则只累加左边的pd[i - 1][j]数组的值 ;
3、相反,则只累加上方dp[i][j - 1];
4、同时出现障碍物时,dp[i][j]设置为0;
5、没有障碍物,就正常相加;
(4)遍历顺序:
也是从[1][1]开始遍历,从浅带到深;
(5)打印dp数组(debug);
2、整体代码如下:
class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {// 获得行数和列数int m = obstacleGrid.size();int n = obstacleGrid[0].size();if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) return 0;// 1、确定dp数组,和上一题类似;vector<vector<int>> dp(m, vector<int>(n));// 2、同样的方法初始化for (int i = 0; i < m; i++) {if (obstacleGrid[i][0] == 1) {for (int j = i; j < m; j++) {dp[i][0] = 0;}break;}dp[i][0] = 1;}for (int j = 0; j < n; j++) {if (obstacleGrid[0][j] == 1) {for (int i = j; i < n; i++) {dp[0][j] = 0;}break;}dp[0][j] = 1;}// 3、遍历顺序for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {// 情况0:当前的坐标有障碍物if (obstacleGrid[i][j] == 1) {dp[i][j] = 0;continue;}// 情况1:左边出现障碍物if (obstacleGrid[i - 1][j] == 1 && obstacleGrid[i][j - 1] != 1) {dp[i][j] = dp[i][j - 1];// 情况2:上方出现障碍物} else if (obstacleGrid[i - 1][j] != 1 && obstacleGrid[i][j -1] == 1) {dp[i][j] = dp[i - 1][j];// 情况3:左右均有障碍物} else if (obstacleGrid[i - 1][j] == 1 && obstacleGrid[i][j -1] == 1){dp[i][j] = 0;// 情况4:没有障碍物} else {dp[i][j] = dp[i][j - 1] + dp[i - 1][j];}}}// 5、打印dp数组// for (int i = 0; i < m; i++) {// for (int j = 0; j < n; j++) {// cout << dp[i][j] << " ";// }// cout << endl;// }return dp[m - 1][n - 1];}
};
今日学习时间:1.5小时;
Nobody can stop me.
我无人可当!