n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

(模板)N 皇后问题(DFS 回溯剪枝)_全排列

上图为 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;
    }
};