n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
解法:
该题和全排列的做法有异曲同工之妙
全排列的做法是在每个位置摆放一个数字,然后递归至下一个位置摆放另外一个数字,直到所有位置摆放完毕后输出一种结果
n皇后的做法和全排列一样,不过在每一次摆放时要判断该位置是否和前面的位置冲突,如果发生冲突则跳过该次操作
以行为递归单位,按列进行尝试
其中对角线可以用一元函数的思想来实现,正对角线可表示为col = row + b,则 b = col - row,为了防止b为负数,可以给b加上一个n
斜对角线可表示为 col = -row + b, b = col + row
这样我们就可以用b来表示每一条对角线,如果对角线上有皇后存在,就可以快速进行判断
const int N = 1010;
class Solution {
public:
int un;
vector<vector<string>> grid; //棋盘
vector<string> solu;
bool col[N],dg[N],udg[N]; //分别表示当前列数
void qdfs(int u){
if(u == un){
grid.push_back(solu); //得出一种解法
return;
}
for(int i = 0; i < un; ++i){
if(!col[i] && !dg[u+i] && !udg[un-u+i]){
col[i] = dg[u+i] = udg[un-u+i] = true;
solu[u][i] = 'Q'; //尝试在这个位置摆放皇后
qdfs(u+1);
solu[u][i] = '.';
col[i] = dg[u+i] = udg[un-u+i] = false;
}
}
}
vector<vector<string>> solveNQueens(int n) {
un = n;
memset(col,false,sizeof(col));
memset(dg,false,sizeof(dg));
memset(udg,false,sizeof(udg));
for(int i = 0; i < n; ++i){
string s = "";
for(int j = 0; j < n; ++j){
s += '.';
}
solu.push_back(s);
}
qdfs(0);
vector<vector<string>> res = grid;
return res;
}
};