今天两道题是对于不同路径的个数的判断。
第一题:
简介:
本题同样我们用动态规划五部曲来进行分析。本题是动态规划二维dp数组的入门题目。
1.确定二维dp数组(dp table)以及下标的含义(重要)
dp[i][j]的定义为:爬到第i层第j个位置有几种走法
2.确定递推公式 (重要)
3.dp数组如何初始化
本题的初始化有点特别,我们可以想象如果我们从起点开始一直向右走,那么右面只有一条路所以值都为1,同理,向下走也同样为1。所以我们初始化直接将直接向右走或者直接向下走都初始化为1。
4.确定遍历顺序
5.看结果与我们所想是否一致
代码实现:
第二题:
简介:
本题是第一题的升级版,题目中添加了障碍。我们同样用动态规划五部曲进行分析。
注:为了方便观看我把障碍的值变为了 -1
for(int i =0;i<obstacleGrid.size();i++){
for(int j=0;j<obstacleGrid[i].size();j++){
if(obstacleGrid[i][j]==1){
dp[i][j]=-1;
}
}
}
1.确定二维dp数组(dp table)以及下标的含义(重要)
dp[i][j]的定义为:爬到第i层第j个位置有几种走法
2.确定递推公式 (重要)
3.dp数组如何初始化
本题初始化时有点不同,因为有障碍所以我们在初始化时要注意的是如果碰到障碍那么我们直接退出循环,不是跳过障碍继续循环。
for(int i=0;i<obstacleGrid[0].size();i++){
if(dp[0][i]==-1){
break;
}
dp[0][i]= 1;
}
for(int i=0;i<obstacleGrid.size();i++){
if(dp[i][0]==-1){
break;
}
dp[i][0]= 1;
}
4.确定遍历顺序
5.看结果与我们所想是否一致
代码实现:
我的方法:
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
vector<vector<int>> dp;
vector<int> dp1(obstacleGrid[0].size());
for(int i=0;i<obstacleGrid.size();i++){
dp.push_back(dp1);
}
for(int i =0;i<obstacleGrid.size();i++){
for(int j=0;j<obstacleGrid[i].size();j++){
if(obstacleGrid[i][j]==1){
dp[i][j]=-1;
}
}
}
for(int i=0;i<obstacleGrid[0].size();i++){
if(dp[0][i]==-1){
break;
}
dp[0][i]= 1;
}
for(int i=0;i<obstacleGrid.size();i++){
if(dp[i][0]==-1){
break;
}
dp[i][0]= 1;
}
for(int i =1;i<obstacleGrid.size();i++){
for(int j=1;j<obstacleGrid[i].size();j++){
if(dp[i][j]==-1)continue;
if(dp[i-1][j] != -1 &&dp[i][j-1] != -1){
dp[i][j]= dp[i-1][j]+dp[i][j-1];
}else if(dp[i-1][j] != -1 && dp[i][j-1] ==-1 ){
dp[i][j]= dp[i-1][j];
}else if(dp[i][j-1] != -1&& dp[i-1][j] == -1){
dp[i][j]= dp[i][j-1];
}
}
}
for(int i=0;i<dp.size();i++){
for(int j=0;j<dp[i].size();j++){
cout<<dp[i][j]<<endl;
}
}
if(dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1]==-1)return 0;
return dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1];
}
};
题解方法:
题解的方式是和我的方式在初始化及之前基本相同,在遍历时题解的方法是遇到障碍将将其变为零,也不会影响后序相加,而我的方法是将有障碍的地方跳过,并且用条件判断将其去掉。
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) //如果在起点或终点出现了障碍,直接返回0
return 0;
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (obstacleGrid[i][j] == 1) continue;
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
};
总结:
今天对路径问题的动态规划方式进行了了解。其实,第一题可以用纯数学的方式解决,在这里就不多介绍。我认为第二题是第一题的衍生题,我们要学会举一反三,第一题会了,第二题应该很简单。继续加油!