UniquePaths
- 问题描述:给定一个起点和终点,找到一共有多少条满足条件的路径。
Unique Paths I
- 给定一个矩阵,起点在左上角,终点在右下角。只能向下走或者向右走。
- 思路:我们当然可以用DFS来做,但是时间复杂度就是O(2(M∗N))。所以我们采用动态规划的方法来做。
- 转移方程如下:dp[i][j]=dp[i−1][j]+dp[i][j−1]。
- 初始化:dp[0:i][0]=1,dp[0][0:j]=1
- 代码:
int uniquePaths(int m, int n) {
int res = 0;
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=0;i<m;i++){
for(int j=0;j<n;j++){
if(i == 0 || j == 0)
continue;
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
res = dp[m-1][n-1];
return res;
}
Unique Paths II
- 给定一个矩阵,起点在左上方,终点在右下方,路径上还有一些点不能走,用1表示。只能走下或右。计算有多少不同的路径。
- 思路:还是动态规划的想法,相比于I,我们更改一个条件:如果当前位置不可走,则dp[i][j] =0;
- 转移方程如下:dp[i][j]=(dp[i−1][j]+dp[i][j−1])∗(grid[i][j]==0)。
- 初始化
- dp[0][0] = grid[0][0] == 0;
- dp[i][0] = dp[i-1][0] && grid[i][0] == 0
- dp[0][j] = dp[0][j-1] && grid[0][j] == 0
- 代码:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = (int) obstacleGrid.size();
if(m == 0)
return 0;
int n = (int) obstacleGrid[0].size();
long long dp[m][n];
memset(dp, 0, sizeof(dp));
if(obstacleGrid[0][0] != 0)
return 0;
dp[0][0] = 1;
for(int i=1;i<m;i++){
if(obstacleGrid[i][0] == 0 && dp[i-1][0] == 1){
dp[i][0] = 1;
}else{
dp[i][0] = 0;
}
}
for(int j=1;j<n;j++){
if(obstacleGrid[0][j] == 0 && dp[0][j-1] == 1){
dp[0][j] = 1;
}else{
dp[0][j] = 0;
}
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
if(obstacleGrid[i][j] == 0)
dp[i][j] = dp[i-1][j] + dp[i][j-1];
else
dp[i][j] = 0;
}
}
return dp[m-1][n-1];
}
Unique Paths III
- 给定一个矩阵,0表示可以走,1表示起点,2表示终点,-1表示障碍物。此时可以向四个方向走。问从起点到终点,将所有可以路过的点路过有且只有一次的走法有多少种。
- 思路
- DFS是一种,我们首先计算出完整的路径我们一共要走的步数,以及起始点和终点的坐标。然后我们有以下终止条件:
- 如果步数达标
- 当前点是终点,res += 1
- 否则,return
- 如果当前点是终点,步数没达标
- 动态规划也是一种思路。
- 整体来说动态规划的思路和DFS比较相似。在leetcode上两者的耗时也基本一致。如下图所示。
- 代码:
class Solution {
public:
bool isVaild(int x, int y, int m, int n){
if(x>=0 && x<m && y>=0 && y<n){
return true;
}
return false;
}
int dxs[4] = {1, 0, -1, 0};
int dys[4] = {0, 1, 0, -1};
void uniquePathsIIIRecursive(const vector<vector<int>>& grid, int m, int n, int x, int y, int step,
int total_step, bool* visits, int& res){
if(step == total_step){
if(grid[x][y] == 2)
res += 1;
return;
}
if(grid[x][y] == 2){
return;
}
for(int dir_id=0;dir_id<4;dir_id++){
int new_x = x + dxs[dir_id];
int new_y = y + dys[dir_id];
if(isVaild(new_x, new_y, m, n)){
int visit_pos = new_x * n + new_y;
if(!visits[visit_pos] && grid[new_x][new_y] != -1){
visits[visit_pos] = true;
uniquePathsIIIRecursive(grid, m, n, new_x, new_y, step + 1, total_step, visits, res);
visits[visit_pos] = false;
}
}
}
}
int uniquePathsIII(vector<vector<int>>& grid) {
int m = (int) grid.size();
if(m == 0){
return 0;
}
int n = (int) grid[0].size();
bool visits[m * n];
memset(visits, false, sizeof(visits));
int total_step = 0;
int start_x = 0;
int start_y = 0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j] == 0 || grid[i][j] == 2){
total_step += 1;
}
if(grid[i][j] == 1){
start_x = i;
start_y = j;
}
}
}
int res = 0;
visits[start_x * n + start_y] = true;
uniquePathsIIIRecursive(grid, m, n, start_x, start_y, 0, total_step, visits, res);
return res;
}
int code(int x, int y, int m, int n){
return 1 << (x * n + y);
}
int uniquePathsIII_V2(vector<vector<int>>& grid) {
int m = (int) grid.size();
if(m == 0){
return 0;
}
int n = (int) grid[0].size();
int start_x;
int start_y;
int target_x;
int target_y;
int target = 0;
for(int i=0;i<m;i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0) {
target |= code(i, j, m, n);
} else {
if (grid[i][j] == 1) {
start_x = i;
start_y = j;
} else {
if (grid[i][j] == 2) {
target |= code(i, j, m, n);
target_x = i;
target_y = j;
}
}
}
}
}
return dp(start_x, start_y, m, n, target_x, target_y, target);
}
int dp(int x, int y, int m, int n, int target_x, int target_y, int to_do){
if(to_do == 0){
if(x == target_x && y == target_y)
return 1;
return 0;
}
if(x == target_x && y == target_y)
return 0;
int ans = 0;
for(int i=0;i<4;i++){
int new_x = x + dxs[i];
int new_y = y + dys[i];
if(isVaild(new_x, new_y, m, n)){
if(to_do & code(new_x, new_y, m, n))
ans += dp(new_x, new_y, m, n, target_x, target_y, to_do ^ code(new_x, new_y, m, n));
}
}
return ans;
}
};