题目链接:https://leetcode-cn.com/problems/n-queens/
总体思路
首先用到了一个int(姑且称之为伪数组)来存储可放置的位置,自然有其好处,省去了繁杂的创建数组的过程,并且便于用位运算进行顺次约束。分为三个约束条件,姑且用line,knife以及fork代替,分别用于,列约束,左斜约束,右斜约束(擅自命名,顺便帮自己记下“左手拿叉,右手拿刀”。
八皇后离不开深度优先搜索,为了思路更加清晰,将生成输出部分抽象为一个generateBoard函数,将生成可行解的部分抽象为一个solve函数,并且用solveNQueen连接两者。
每次深度搜索时,先判断是否为零,若为零,则意味着此时可以终止深度搜索。若不为零,则取得位数最低的一个零1进行下一步的深度搜索,回溯时将其置1,避免死循环。
生成部分,首先全部置’.’,然后根据solutions将放置皇后处置’Q’。
用到了高效率位运算:
•int __builtin_ctz (unsigned int x)
返回x的二进制下末尾的0的个数
具体实现
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
auto solutions = vector<vector<string>>();
auto queens = vector<int>(n, -1);
solve(solutions, queens, n, 0, 0, 0, 0);
return solutions;
}
void solve(vector<vector<string>> &solutions, vector<int> &queens, int n, int row, int line, int knife, int fork) {
if (row == n) {
auto board = generateBoard(queens, n);
solutions.push_back(board);
} else {
int availablePositions = ((1 << n) - 1) & (~(line | knife | fork));
int & ap=availablePositions;
while (ap != 0) {
int position = ap & (-ap);
ap = ap & (ap - 1);
int column = __builtin_ctz(position);
queens[row] = column;
solve(solutions, queens, n, row + 1, line | position, (knife | position) >> 1, (fork | position) << 1);
queens[row] = -1;
}
}
}
vector<string> generateBoard(vector<int> &queens, int n) {
auto board = vector<string>();
for (int i = 0; i < n; i++) {
string row = string(n, '.');
row[queens[i]] = 'Q';
board.push_back(row);
}
return board;
}
};