每日一題,防止癡呆 = =
一、題目大意
一個機器人位於一個 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];
}
};
如果有問題,歡迎大家指正!!!