1 62. 不同路径
自己试着写写,二维dp数组,还是五步曲,AC代码:
class Solution {
public:
int dp[105][105];// (i,j) 表示到达这个格子最多几条不同的路径
/*
状态转移:
dp[i][j] = dp[i-1][j] + dp[i][j-1];
dp数组初始化(初始化 第一行和第一列)
dp[0][0] = 0
dp[0][x] = 1
dp[x][0] = 1
顺序:
for(i++)中for(j++)
模拟一下
2*3
0 1 1
1 2 3
*/
int uniquePaths(int m, int n) {
// 原来 用dp 不用搜索 是因为怕超时
dp[0][0] = 0;
for(int i = 1; i < n; i++)
dp[0][i] = 1;
for(int i = 1; i < m; i++)
dp[i][0] = 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];
if(m == 1 && n == 1)return 1; // 特殊处理
return dp[m-1][n-1];
}
};
2 63. 不同路径 II(有障碍物版本的上一题)
有障碍物就是加一堆if-else ,自己写的 ,然后debug半天很多边界通过反复提交才试出来,比如:
if(m == 1 && n == 1)return obstacleGrid[0][0] ^ 1; // 因为dp[0]设置为0 所以要特殊处理
if(obstacleGrid[0][0] || obstacleGrid[n-1][m-1] || dp[n-1][m-1] == -1)return 0; //特殊处理起点有障碍物 、终点有障碍物、 终点不可达(三种情况)
AC代码:
class Solution {
public:
int dp[105][105];// (i,j) 表示到达这个格子最多几条不同的路径 -1表示不可达
/*
状态转移:
if(obs[i-1][j] == 0 && dp[i-1][j] != -1) // 上一个不是障碍物且可达
dp[i][j] += dp[i-1][j]
if(obs[i][j-1] == 0 && dp[i][j-1] != -1) // 左边一个不是障碍物且可达
dp[i][j] += dp[i][j-1]
if((obs[i-1][j] == 1 || dp[i-1][j] == -1) && (obs[i][j-1] == 1 || dp[i][j-1] == -1))if(obstacleGrid[i][j]) // 两个都不能达到我 或者我本身是障碍物
dp[i][j] = -1
dp数组初始化(初始化 第一行和第一列)
dp[0][0] = 0
dp[0][x] = 1 这一行第一个障碍物 后面的格子都不可达 设为-1
dp[x][0] = 1 这一列第一个障碍物 下面的格子都不可达 设为-1
顺序:
for(i++)中for(j++)
模拟一下
3*3
0 1 1
1 -1 1
1 1 1
*/
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid)
{
dp[0][0] = 0;
int n = obstacleGrid.size(); // 行
int m = obstacleGrid[0].size();
int x = 1;
for(int i = 1; i < n; i++)
{
if(obstacleGrid[i][0] == 1)x = -1;
dp[i][0] = x;
}
x = 1;
for(int i = 1; i < m; i++)
{
if(obstacleGrid[0][i] == 1)x = -1;
dp[0][i] = x;
}
for(int i = 1; i < n;i++)
for(int j = 1; j < m; j++)
{
if(obstacleGrid[i-1][j] == 0 && dp[i-1][j] != -1)
dp[i][j] += dp[i-1][j];
if(obstacleGrid[i][j-1] == 0 && dp[i][j-1] != -1)
dp[i][j] += dp[i][j-1];
if((obstacleGrid[i-1][j] == 1 || dp[i-1][j] == -1) && (obstacleGrid[i][j-1] == 1 || dp[i][j-1] == -1)) // 两个都满
dp[i][j] = -1;
if(obstacleGrid[i][j])dp[i][j] = -1;
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
cout << dp[i][j] << " ";
cout << endl;
}
if(m == 1 && n == 1)return obstacleGrid[0][0] ^ 1; // 因为dp[0]设置为0 所以要特殊处理
if(obstacleGrid[0][0] || obstacleGrid[n-1][m-1] || dp[n-1][m-1] == -1)return 0; //特殊处理起点有障碍物 、终点有障碍物、 终点不可达
return dp[n-1][m-1];
}
};
看了题解,思路差不多,就是它遇到障碍dp[i][j]保持0,然后状态转移方程就可以写的很简单。
直接复制粘贴的代码:
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];
}
};