【回溯】【leetcode】N皇后:返回所有不同的解决方案

题目:

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

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例 1:


输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

来源:

51. N 皇后

面试题 08.12. 八皇后

2题一样,相同代码提交即可。

解题思路:回溯

定义一个path,记录每行中皇后的列位置,path[i]表示第i行的皇后所在的列号。

  • 结果满足条件:放置的皇后数量等于n时,输出并退出。
  • 递归调用条件:检查当前节点是否与之前有冲突,如果没有,则继续递归。
  • 检查当前位置能否放置皇后:一行一个皇后,所以行上不冲突,不用检查。只需检查列、对角线、反对角线是否已放置。

如下图,绿色对角线上行号、列号的关系:行号-列号是相同的;橙色对角线行号、列号关系:行号+列号是相同的。冲突检查参见代码中check()函数。

class Solution {
public:
    vector< vector<string> > result;
    vector<int> path; // path[i]:第i行皇后放置的位置
    vector< vector<string> > solveNQueens(int n) {
        back(n, 0);
        return result;
    }

    // 放置第k个皇后,k从0开始
    void back(int n, int k) {
        if (k == n) {
            out();
            return;
        }
        // 找到可以放置的列
        for (int i = 0; i < n; i++) {
            if (check(i)) {
                path.push_back(i);
                back(n, k+1);
                path.pop_back();
            }
        }
    }
    // 检查第path.size()行,第p列是否合法
    bool check(int p) {
        int d1 = p - path.size(); // 列号-行号
        int d2 = p + path.size(); // 列号+行号
        for (int i = 0; i < path.size(); i++) {
            if (path[i] == p || // 列
                d1 == path[i] - i || // 左上-右下
                d2 == path[i] + i) { // 右上-左下
                return false;
            }
        }
        return true;
    }
    void out() {
        vector<string> ret;
        int n = path.size();
        for (int i = 0; i < n; i++) {
            string t(n, '.');
            t[path[i]] = 'Q';
            ret.push_back(t);
        }
        result.push_back(ret);
    }
};

猜你喜欢

转载自blog.csdn.net/hbuxiaoshe/article/details/115077166
今日推荐