今天的题目深深地体会到了动态规划,遇到问题时应该先想办法进行拆解,寻找不同部分之间的关系。
思路:观察易发现dp[i][j]点的路径对于其上方和左方的路径之和,再考虑初始化。首行和首列的点路径条数都是1,易写出如下代码:
class Solution {
public:
int uniquePaths(int m, int n) {
if(m==1 && n==1) return 1;
int dp[m][n];
for(int i=0;i<m;i++) dp[i][0]=1;
for(int j=0;j<n;j++) dp[0][j]=1;
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
反思:一开始我一直在纠结该怎么记录路径条数,想用一个变量去记录而忽视了去寻找后一阶段与前一阶段的关系。遇到问题时,我们应该首先对问题进行拆分,即答案可以由哪些组成,再去考虑初始化,逐个击破。
问题2:63. 不同路径 II - 力扣(LeetCode)
思路:障碍物处的路径和为0,同时当障碍物在最上面或者最左边时,遇到障碍物则停止初始化(因为只能向下和向右走)。代码如下:
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int a=obstacleGrid.size();
int b=obstacleGrid[0].size();
vector<vector<int>> dp(a,vector<int>(b,0));
if(obstacleGrid[0][0]==1 || obstacleGrid[a-1][b-1]==1) return 0;
for(int i=0;i<a && obstacleGrid[i][0]==0;i++) dp[i][0]=1;
for(int j=0;j<b && obstacleGrid[0][j]==0;j++) dp[0][j]=1;
for(int i=1;i<a;i++){
for(int j=1;j<b;j++){
if(obstacleGrid[i][j]==1) continue;
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[a-1][b-1];
}
};
反思:当题目中出现新条件时,想想它带来的影响,还是要从状态上去思考。