LeetCode 51. N 皇后(经典回溯问题)

博客围绕 n 皇后问题展开,该问题是将 n 个皇后置于 n×n 棋盘,使皇后彼此不能相互攻击。介绍了解题思路,先定义解集,从第 0 行第 0 列开始放置皇后,判断上方及对角线有无冲突,利用回溯法求解,最终 8 皇后问题有 92 个解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
在这里插入图片描述
上图为 8 皇后问题的一种解法。

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

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

在这里插入图片描述

提示:
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

思路

  1. 题述里最后输出的是一个一维数组,其中每个数组元素是一个vector,代表了一张棋盘。 vector<vector<string> > res;也就是说每张棋盘的形式是vector,所以先定义一个内容为vector类型的vector,用来装多张棋盘,作为最终的解集。初始将每张棋盘设置为共n组,每组n个“.”的初始值,也就是每张棋盘初始为空。vector<string> chess(n, string(n, '.'));
  2. 从第0行开始考虑放置皇后,首先从第0列开始放,也就是当前坐标是chess[0][0],判断当前位置的上方,左上对角线、右上对角线有无皇后,没有则当前位置可以放置皇后,这行已经不能在放下一个皇后了,再考虑下一行的第0列…如果放置皇后之后在上方及对角线上有皇后冲突了,则不在此位置放,考虑本行的下一个位置。如此循环,当行已经超过了棋盘行数n后就不能再放了,此时一定能得到一张八皇后的棋盘,将其添加到解集中即可。
  3. 回溯的通用模版:
void backTrack(){
	for(遍历){
		chess[row][column] = 'Q';//放置皇后
		backTrack();//递归
		chess[row][column];//函数能执行到这说明此位置放皇后的话无解
	}
}

解答

class Solution {
public:
//定义保存最终结果的一维数组,大小为1*m,每一个数组元素是一个vector,代表一张棋盘
vector<vector<string> > res;
int N = 0;
    vector<vector<string>> solveNQueens(int n) {
        N = n;
        //初始化为n个“......”的vector
        //形式:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
        vector<string> chess(n, string(n, '.'));
        //从第0行开始放置皇后
        backTrack(chess, 0);
        return res;
    }
    void backTrack(vector<string>& chess, int row){
        if(row == N){//已经到了最后一行
            res.push_back(chess);
            return;
        }
        //从第0列开始尝试放皇后
        for(int column = 0;column < N;++ column){
            if(isValue(chess, row, column)){
                chess[row][column] = 'Q';
                backTrack(chess, row + 1);
                chess[row][column] = '.';
            }
        }
    }
    //判断chess[row][column]的上方、左上方对角线、右上方对角线有无皇后
    bool isValue(vector<string>& chess, int row, int column){
        //判断当前坐标的上方有无皇后
        for(int i = 0;i < N; ++ i)
            if(chess[i][column] == 'Q') return false;
        //判断当前坐标的左上对角线有无皇后
        for(int i = row-1,j = column-1;i >= 0 && j <= N; --i, --j)
            if(chess[i][j] == 'Q') return false;
        //判断当前坐标的右上对角线有无皇后        
        for(int i = row-1, j = column+1;i >= 0 && j <= N; --i, ++j)
            if(chess[i][j] == 'Q') return false;
        return true;
    }
};

最终8皇后问题执行了15720次,共有92个解:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值