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;
}
}
}
};