[Leetcode] 63, 51, 52
63. Unique Paths II
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1
and 0
respectively
in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[ [0,0,0], [0,1,0], [0,0,0] ]
The total number of unique paths is 2
.
Note: m and n will be at most 100.
Solution(1): 深搜+備忘錄法,記得邊界情況(起點和終點)和記錄的資料不能出錯。
Code:
class Solution { public: int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) { if(obstacleGrid.size()==0 || obstacleGrid[0].size()==0) return 0; if(obstacleGrid.back().back()==1 || obstacleGrid[0][0]==1) return 0; obstacleGrid.back().back() = -1; return uniquePathsWithObstacles(obstacleGrid, 0, 0); } private: int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid, int x, int y){ if(obstacleGrid[x][y]==1) return 0; if(obstacleGrid[x][y]<0) return -1*obstacleGrid[x][y]; //已經計算過的部分使用負數標記那一個到終點的種類,數量為0的情況記為1,即值為0時這個位置沒有計算過 int ans = 0; if(x<obstacleGrid.size()-1){ ans += uniquePathsWithObstacles(obstacleGrid, x+1, y); } if(y<obstacleGrid[0].size()-1){ ans += uniquePathsWithObstacles(obstacleGrid, x, y+1); } if(ans>0) obstacleGrid[x][y] = -1*ans; else obstacleGrid[x][y] = 1; return ans; } };
Solution(2): 動規。
Code:
class Solution { public: int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) { if(obstacleGrid[0][0]==1 || obstacleGrid.back().back()==1) return 0; obstacleGrid.back().back() = 1; int m = obstacleGrid.size(); int n = obstacleGrid[0].size(); for(int i=n-2; i>=0; i--){ if(obstacleGrid[m-1][i]==0) obstacleGrid[m-1][i] = obstacleGrid[m-1][i+1]; else obstacleGrid[m-1][i] = 0; } for(int i=m-2; i>=0; i--){ if(obstacleGrid[i][n-1]==0) obstacleGrid[i][n-1] = obstacleGrid[i+1][n-1]; else obstacleGrid[i][n-1] = 0; } for(int i=m-2; i>=0; i--){ for(int t=n-2; t>=0; t--){ if(obstacleGrid[i][t]==0) obstacleGrid[i][t] = obstacleGrid[i+1][t]+obstacleGrid[i][t+1]; else obstacleGrid[i][t] = 0; } } return obstacleGrid[0][0]; } };
51. N-Queens
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q'
and '.'
both
indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ]
Solution:
經典的回溯題,深搜+剪枝。對於剪枝,我的做法是在原陣列中直接將不能放Queen的位置標記為'.'。
Code:
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> ans;
string s = "";
for(int i=0; i<n; i++) s.push_back('+');
vector<string> path(n);
fill_n(path.begin(), n, s);
solveNQueens(0, path, ans);
return ans;
}
private:
void solveNQueens(int i, vector<string>& path, vector<vector<string>>& ans){
//cout<<i<<endl;
int n = path.size();
if(i==n){
ans.push_back(path);
return;
}
//遍歷第i行, '+'表示沒有擺放任何值, 'Q'表示擺放了Queen, '.'表示無法擺放Queen
for(int t=0; t<n; t++){
if(path[i][t]=='+'){
path[i][t] = 'Q';
vector<string> newpath = setQueen(i, t, path);//TODO
//for(int i=0; i<newpath.size(); i++)
//cout<<newpath[i]<<endl;
solveNQueens(i+1, newpath, ans);
path[i][t] = '.';
}
}
}
vector<string> setQueen(int i, int t, vector<string>& path){
vector<string> newpath = path;
int n = path.size();
for(int j=i+1; j<n; j++)
newpath[j][t] = '.';
for(int j=t+1; j<n; j++)
newpath[i][j] = '.';
for(int j=i+1,q=t+1; j<n && q<n; j++,q++)
newpath[j][q] = '.';
for(int j=i+1,q=t-1; j<n && q>=0; j++,q--)
newpath[j][q] = '.';
return newpath;
}
};
52.
N-Queens II
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
Solution: 比上面一題要簡單一些,不需要輸出解集,只需要輸出總數即可,在深搜的時候使用一個全域性變數記錄總數,搜到一個解就+1。換了一種記錄的方式,不再直接記錄在原棋盤資料中,因為這題不需要生成解,直接使用是三個陣列來記錄即可,因為棋盤上一個資料可以投影到四個方向,橫向、縱向、主對角線方向、副對角線方向,這四個方向一個點都只能存在一個Queen,因此使用三個陣列記錄三個方向的放棋方式,一個方向用於深搜。
Code:
class Solution {
public:
int totalNQueens(int n) {
this->columns = vector<bool>(n,true);
this->principal_diagonals = vector<bool>(n,true);
this->counter_diagonals = vector<bool>(n,true);
totalNQueens(0, n);
return num;
}
private:
vector<bool> columns;//投影:y, true為可以填入Queen, false為不可填入Queen
vector<bool> principal_diagonals;//投影:x-y+n-1
vector<bool> counter_diagonals;//投影:x+y
int num = 0;
void totalNQueens(int x, int n){
//第x行往下有多少解
if(x==n){
num++;
return;
}
for(int y=0; y<n; y++){
if(columns[y] && principal_diagonals[x-y+n-1] && counter_diagonals[x+y]){
columns[y] = false;
principal_diagonals[x-y+n-1] = false;
counter_diagonals[x+y] = false;
totalNQueens(x+1, n);
columns[y] = true;
principal_diagonals[x-y+n-1] = true;
counter_diagonals[x+y] = true;
}
}
}
};