51. N 皇后

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

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

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

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

示例 1:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
class Solution {
public:
    vector<vector<string>> result;
    bool isValid(int row, int col, vector<string>& chessboard, int n){
        for (int i = 0; i < row; i++){
            if (chessboard[i][col] == 'Q')
                return false;//列
        }
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--){
            if (chessboard[i][j] == 'Q')
                return false;//左上
        }
         for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++){
            if (chessboard[i][j] == 'Q')
                return false;//右上
        }
        return true;
    }
    void backtracking(int n, int row, vector<string>& chessboard){
        if (row >= n){
            result.push_back(chessboard);
            return;
        }
        for (int i = 0; i < n; i++){
            if (isValid(row, i, chessboard, n)){
                chessboard[row][i] = 'Q';
                backtracking(n, row + 1, chessboard);
                chessboard[row][i] = '.';
            }
        }
    }
    vector<vector<string>> solveNQueens(int n) {
        //std::vector<std::string> chessboard(n, std::string(n, '.'));
        vector<string> chessboard(n, string(n, '.'));
        backtracking(n, 0, chessboard);
        return result;
    }
};

皇后们的约束条件:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线                                                                                                                               3 * 3 的棋盘,将搜索过程抽象为一棵树,如图:

从图中,可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。

那么我们用皇后们的约束条件,来回溯搜索这棵树,只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了

回溯三部曲:

递归函数参数:

全局变量二维数组result来记录最终结果。

参数n是棋盘的大小,然后用row来记录当前遍历到棋盘的第几层了。

递归终止条件:

当递归到棋盘最底层(也就是叶子节点)的时候,就可以收集结果并返回了。

if (row == n) {
    result.push_back(chessboard);
    return;
}

单层搜索的逻辑: 

递归深度就是row控制棋盘的行,每一层里for循环的col控制棋盘的列,一行一列,确定了放置皇后的位置。

每次都是要从新的一行的起始位置开始搜,所以都是从0开始。

  • 验证棋盘是否合法

按照如下标准去重:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线 (45度和135度角)

没有在同行进行检查:因为在单层搜索的过程中,每一层递归,只会选for循环(也就是同一行)里的一个元素,所以不用去重了。

参考:代码随想录 (programmercarl.com)

描述

N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后,
要求:任何两个皇后不同行,不同列也不在同一条斜线上,
求给一个整数 n ,返回 n 皇后的摆法数。

#include <codecvt>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 the n
     * @return int整型
     */
    int count = 0;
    bool isValid(int row, int col, int n, vector<string> chessboard){
        for (int i = 0; i < row; i++){
            if (chessboard[i][col] == 'Q')
                return false;
        }
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--){
            if (chessboard[i][j] == 'Q')
                return false;
        }
        for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++){
            if (chessboard[i][j] == 'Q')
                return false;
        }
        return true;
    }
    void backtracking(int row, int n, vector<string> chessboard){
        if (row == n){
            count++;
            return;
        }
        for (int i = 0; i < n; i++){
            if (isValid(row, i, n, chessboard)){
                chessboard[row][i] = 'Q';
                backtracking(row + 1, n, chessboard);
                chessboard[row][i] = '.';
            }
        }
    }
    int Nqueen(int n) {
        // write code here
        vector<string> chessboard(n, string(n, '.'));
        backtracking(0, n, chessboard);
        return count;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值