每日一题,防止痴呆 = =
一、题目大意
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-ii
二、题目思路以及AC代码
思路
这题我一开始傻傻的想到dfs,可能是反应,看到地图就想dfs和bfs = =,然后也没考虑时间复杂度就写了,结果不出意料的TLE。
然后抛开dfs的思路,再一看,好像就是很明显的动态规划,只需要设dp[i][j]表示从(i, j)处到达终点的路径条数就可以了,递推公式如下:
dp[i][j] = obstacleGrid[i][j] ? 0 : dp[i+1][j] + dp[i][j+1]
这里注意到我们其实在计算dp[i][j]的时候,只用到了它下面和右边的元素,所以可以用滚动数组进行优化,将空间复杂度优化为O(cols),cols是列数
AC代码
最开始傻傻的dfs方法,写了就别浪费
class Solution {
private:
int ex, ey;
int* dx;
int* dy;
bool** vis;
public:
int dfs(vector<vector<int>>& obstacleGrid, int x, int y) {
if (x == ex - 1 && y == ey - 1) return obstacleGrid[x][y] ? 0 : 1;
int res = 0;
for (int i=0;i<2;i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= ex || ny >= ey || vis[nx][ny] || obstacleGrid[nx][ny]) continue;
vis[nx][ny] = true;
res += dfs(obstacleGrid, nx, ny);
vis[nx][ny] = false;
}
return res;
}
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
dx = new int[2];
dy = new int[2];
dx[0] = 1; dx[1] = 0;
dy[0] = 0; dy[1] = 1;
ex = obstacleGrid.size();
ey = obstacleGrid[0].size();
vis = new bool*[ex];
for (int i=0;i<ex;i++) vis[i] = new bool[ey];
for (int i=0;i<ex;i++) {
for (int j=0;j<ey;j++) {
vis[i][j] = false;
}
}
return obstacleGrid[0][0] ? 0 : dfs(obstacleGrid, 0, 0);
}
};
动态规划:
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int rows = obstacleGrid.size();
int cols = obstacleGrid[0].size();
long long dp[cols];
dp[cols-1] = obstacleGrid[rows-1][cols-1] ? 0 : 1;
for (int i=cols-2;i>=0;i--) {
dp[i] = obstacleGrid[rows-1][i] ? 0 : dp[i+1];
}
for (int i=rows-2;i>=0;i--) {
for (int j=cols-1;j>=0;j--) {
if (j == cols - 1) dp[j] = obstacleGrid[i][j] ? 0 : dp[j];
else dp[j] = obstacleGrid[i][j] ? 0 : dp[j] + dp[j+1];
}
}
return dp[0];
}
};
如果有问题,欢迎大家指正!!!