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.."] ]tag: backtracking
经典问题,九皇后问题,利用回溯算法。
皇后的攻击范围是同一行,同一列,同一斜线。所以同一行只能有一个皇后,我们可以按行插入皇后。
每次插入新的皇后时,检测该皇后是否会攻击到现有的皇后。如果发生冲突,则尝试该行的下一列。如果所有的列都不行,则返回上一层–即上一行。
如果插入皇后时不发生冲突,则进入下一层–即下一行,继续搜索。
该算法还有优化的空间。我为了让算法直观,用了一个bool [][] board变量表示当前棋盘的状态。true表示该单元格被皇后占据,false表示空。
实际上,我们可以用一个一位数组int a[n]表示棋盘状态,下标n表示第n行,a[n]的值表示该行皇后所处的列,然后进行搜索。在下一题中: N-Queens II,我用了这个优化的算法。
class Solution {
public:
//I try to fill the board row by row
vector<vector<string> > solveNQueens(int n) {
vector<vector<bool> > board(n, vector<bool>(n, false));//false means empty; true means occupied by a queen
vector<vector<string>> re;
if(n == 0){
return re;
}
//fill the first row
for(int j = 0; j < n; j++){
board[0][j] = true;
_solveQueens(1, board, re);
board[0][j] = false;
}
return re;
}
void _solveQueens(int row, vector<vector<bool> > &board, vector<vector<string> > &re){
int size = board.size();
if(row == size){//finish
re.push_back(generateResult(board));
return;
}
//not finish
for(int j = 0; j < size; j++){
board[row][j] = true;
if(checkBoard(board, row, j) == true){//leagal
_solveQueens(row + 1, board, re);
}
board[row][j] = false;
}
}
vector<string> generateResult(vector<vector<bool> > &board){
vector<string> strs;
string s;
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board.size(); j++){
char c = board[i][j] == true?'Q': '.';
s.push_back(c);
}
strs.push_back(s);
s.clear();
}
return strs;
}
bool checkBoard(vector<vector<bool> > &board, int row, int column){
int size = board.size();
for(int k = 0; k < size; k++){
//check row
if(board[row][k] == true && k != column){
return false;
}
//check column
if(board[k][column] == true && k != row){
return false;
}
//check diagonal
int r0 = row - k;
int c0 = column - k;
int c1 = column + k;
bool flag = false;
if(r0 >= 0 && c0 >= 0){
flag |= board[r0][c0];
}
if(r0 >= 0 && c1 < size){
flag |= board[r0][c1];
}
//no need to check below part of the board
if(flag == true && k != 0){
return false;
}
}
return true;
}
};

