题目描述
问题分析
何为不能攻击?攻击范围:同行、同列、同对角线。在除此以外的位置安全。
所以需要对棋盘进行数字化表示,我们将棋盘看作是一个矩阵,安全位置用0占位,受攻击位置为1,且攻击位置在皇后所在位置的临近8个方向。在此方向上遍历棋盘将所有攻击位置至1:
放置皇后的功能函数:
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> result;//存放最终结果
vector<vector<int>>mark;//标记棋盘,客房置位置为0,不可放置为1
vector<string>location;//记录某一次存放的位置 Q
//初始化
for (int i = 0; i < n; i++) {
mark.push_back(vector<int>());
for (int j = 0; j < n; j++) {
mark[i].push_back(0);
}
location.push_back("");
location[i].append(n, '.');
}
generate(0, n, location, result, mark);
return result;
}
private:
//放置皇后的功能函数
void put_down_the_queue(int x, int y, vector<vector<int>>& mark) {
//方向
static const int dx[] = { -1,1,0,0,-1,-1,1,1 };
static const int dy[] = { 0,0,-1,1,-1,1,-1,1 };
mark[x][y] = 1;//皇后位置设为1
//遍历棋盘,找出皇后可以攻击的位置
for (int i = 1; i < mark.size(); i++) {
//8个方向上
for (int j = 0; j < 8; j++) {
int new_x = dx[j] * i + x;
int new_y = dy[j] * i + y;
if (new_x < mark.size() && new_x >= 0 && new_y < mark.size() && new_y >= 0) {
mark[new_x][new_y] = 1;
}
}
}
}
//k记录皇后个数(正在放置第k行位置上的皇后)
void generate(int k, int n, vector<string>& location, vector<vector<string>>& result, vector<vector<int>>& mark) {
//递归结束的条件
if (k == n) {
result.push_back(location);
return;
}
//遍历k行上的i列
for (int i = 0; i < n; i++) {
//如果能放置
if (mark[k][i] == 0) {
vector<vector<int>>temp_mask = mark;//记录回溯前的mark
location[k][i] = 'Q';//记录当前皇后位置
put_down_the_queue(k, i, mark); //放置新皇后[]
//若可执行
generate(k + 1, n, location, result, mark);//递归下一行皇后位置
//不可执行
mark = temp_mask;//将mark重新赋值为回溯前状态
location[k][i] = '.';//重置该位置皇后信息
}
}
}
};