leetcode51 N皇后

题目:

N皇后问题:将n个皇后放置在\(n\times n\)的棋盘上,并且皇后彼此之间不能相互攻击。给定一个整数n,返回所有不同n皇后问题的具体解。
示例:

输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],

["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

题目链接:https://leetcode-cn.com/problems/n-queens

思路:

n皇后问题的经典解法便是回溯,我们当然可以一一列举出棋盘上八个皇后所有可能的位置分布,然后再逐一判断满足条件,但通常我们无法承受这样的枚举量。而回溯法是将生成和检查过程有机地结合起来,减少不必要的枚举。
具体到问题中,显然所有皇后都应出现在不同的行和列中,我们逐行放入一个皇后,将列一一列举,判断当前放入皇后与此前放入的皇后是否会在列以及对角线上冲突,如果冲突,继续枚举下一列,否则,放入该皇后。
通过解答树可以帮助理解其中的回溯过程。

代码:

class Solution {
public:
    int C[100] = {-1}; // C[i]=j表示第i行的皇后被放置在第j列
    void search(int n, int cur, vector<vector<string>> &ans){
        if(cur == n){
            vector<string> one_sol;
            for(int i = 0; i < n; ++i){
                string str(n, '.');
                for(int j = 0; j < str.size(); ++j){
                    if(j == C[i]) str[j] = 'Q';    //根据C[i]可以知道Q放置在哪一列
                }
                one_sol.push_back(str);
            }
            ans.push_back(one_sol);
        }else for(int i = 0; i < n; ++i){ //对每一列
            int ok = 1;
            C[cur] = i;            //尝试将cur行的皇后放到i列
            for(int j = 0; j < cur; ++j){  //判断是否与此前放入的皇后冲突
                if(C[cur] == C[j] || cur+C[cur] == j+C[j] || cur-C[cur] == j-C[j]){ //行+列表示副对角线,行-列表示主对角线
                    ok = 0; break;
                }
            }
            if(ok) search(n, cur+1, ans);  //不冲突就寻找下一行皇后放置的位置
        }
    }
    
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> ans;
        search(n, 0, ans);
        return ans;
    }
};
posted @ 2019-09-08 16:39  patrolli  阅读(139)  评论(0编辑  收藏  举报