[算法题解详细]DFS解力扣51N皇后

文章目录

题目

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

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

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

示例1
请添加图片描述

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

示例2

输入:n = 1
输出:[["Q"]]

提示

 1. 1 <= n <= 9
 2. 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

思路

这题我们可以用全排列的思想来做,首先初始化棋盘,然后遍历整个棋盘,对每个点进行判断,如果这个点是可以放置皇后的,则放置皇后,反之复原成初始值,下面我们进入代码

代码

首先在主函数中初始化棋盘,然后在类中定义一个ans容器用于存储答案

class Solution {
    
    
public:
    vector<vector<string>> ans;
    int N;
    vector<vector<string>> solveNQueens(int n) {
    
    
        ans.clear();
        N = n;
        vector<string> chessboard(n, string(n, '.'));
        dfs(0, chessboard);
        return ans;
    }
};

然后是dfs函数,出口条件还是当递归深度等于n的时候,将当前修改的棋盘插入ans容器中,然后是循环当前行,因为N皇后的规定一行只能有一个皇后,在循环中判断当前位置是否可放置皇后,这里要注意回溯的写法

void dfs(int u, vector<string>& chessboard) {
    
    
        if(u == N) {
    
    
            ans.push_back(chessboard);
            return;
        }
        for(int i = 0; i < N; i++) {
    
    
            if(isOk(u , i, chessboard)){
    
    
                chessboard[u][i] = 'Q';
                dfs(u + 1, chessboard);
                chessboard[u][i] = '.';
            }
        }
}

然后是这个isOk()函数,我们传入行列和棋盘用于判断当前位置是否可以放置皇后

那么我们如何判断当前位置是否可放置皇后呢,这就需要看题目的规定:
任何两个皇后都不能处于同一条横行、纵行或斜线上。

横行这里我们不需要管了,因为如果横行有问题的话,会在后面发现不合适然后直接回溯

纵行我们通过传入的行列,让循环变量从0开始一直到当前列的前一列判断,如果这些位置有皇后的存在,则直接返回false,也就是传入的当前位置是不能放置皇后的,等循环结束后如果还没有返回,则进入下一个判断

bool isOk(int row, int col, vector<string>& chessboard) {
    
    
        for(int i = 0; i < row; i++) {
    
    
            if(chessboard[i][col] == 'Q') {
    
    
                return false;
            }
        }
}

下一个判断则是斜线,我们分成两种斜线,一个45度斜线一个135度斜线
首先看135度斜线
请添加图片描述
我们看坐标之间的关系,看上图,红色代表当前位置,斜线上方的位置就由当前位置的行-1,列-1得到

判断135度这条斜线上从起点到当前位置是否已经放置皇后,就需要我们从最上面开始一直遍历到当前位置,循环判断,如果已经有位置放置了皇后,则直接返回false,若循环结束还没有返回,表示当前135度斜线上是没有皇后的,就进入下一个判断

 bool isOk(int row, int col, 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;
            }
        }
}

下一个判断则是35度斜线
请添加图片描述
这条斜线坐标之间的关系也是十分清晰的,就是由当前位置的行-1,列+1得到

注意
这里要注意一点就是,如上图,我们不需要去遍历(1 , 2)这个当前位置下面的(2 , 1)和(3 , 1)两个位置,我们只需要遍历从(0, 3)到当前位置(1 , 2),等下一层或下下层递归下面的位置才会被遍历到

bool isOk(int row, int col, 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;
}

我们要注意在这些判断都没有返回false之后,我们要返回true表示当前位置是可以放置皇后的,因为我们已经判断了当前位置的横行,纵行,和左右斜线位置上都没有皇后的存在,是符合题目规则的。

最后把代码整合一下
完整代码:

class Solution {
    
    
public:
    vector<vector<string>> ans;
    int N;
    bool isOk(int row, int col, 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 dfs(int u, vector<string>& chessboard) {
    
    
        if(u == N) {
    
    
            ans.push_back(chessboard);
            return;
        }
        for(int i = 0; i < N; i++) {
    
    
            if(isOk(u , i, chessboard)){
    
    
                chessboard[u][i] = 'Q';
                dfs(u + 1, chessboard);
                chessboard[u][i] = '.';
            }
        }
    }
    vector<vector<string>> solveNQueens(int n) {
    
    
        ans.clear();
        N = n;
        vector<string> chessboard(n, string(n, '.'));
        dfs(0, chessboard);
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/m0_61607810/article/details/121233446