力扣 51. N 皇后

发布时间 2023-03-28 20:10:28作者: 付玬熙

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

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 <= n <= 9

题解

这题先按思路敲,不要忙着写细节(比如isValid),写个注释放在函数里面就行,先把大体框架写完,思路捋清楚,再回头去写细节。

首先,可以把初始地图cur全初始化为.,后面单独修改需要的位置为Q

递归函数每次传入当前行row,函数目的是寻找当前行row中哪一列的位置可以作为合法放置的位置。所以在函数中,遍历列col0n,面对当前位置cur[row][col],需要做以下操作:

  • 检查cur[row][col]是否合法。编写判断函数isvalid,因为每次都是合法才在此位置放置皇后,所以只需要判断到当前位置而不是整个地图。针对row,col分别判断三个条件:
    • 判断行,行只需要判断0row
    • 判断列 ,同样0col
    • 斜线,分为 左上方 和 右上方
  • 如果合法,将此位置字符设置为Q,放置皇后,然后row+1进入下次递归,出此递归之后,恢复字符串为.,撤销当前位置的选择。

row=n时,表明已经完成了对每一行的搜寻,将当前地图cur加入结果中。

查看代码
 class Solution {
public:
    vector<vector<string>> res;
    vector<string> cur;//当前图
    bool isValid(int& row,int& col,int &n){
        //判定在row,col位置放置皇后是否合法,每次都是合法才加,所以只需要针对row,col分别判断三个条件
        //1.判断行
        for(int i=0;i<row;++i){
            if(cur[i][col]=='Q')
                return false;
        }
        //2.判断列
        for(int i=0;i<col;++i){
            if(cur[row][i]=='Q')
                return false;
        }
        //3.斜线
        //3.1左上方
        int i=row;
        int j=col;
        while(i>=0&&j>=0){
            if(cur[i][j]=='Q')
                return false;
            --i;
            --j;
        }
        //3.2右上方
        i=row;
        j=col;
        while(i>=0&&j<n){
            if(cur[i][j]=='Q')
                return false;
            --i;
            ++j;
        }
        return true;
    }
    //每次传入row即可
    void work(int& n,int row){
        if(row==n){//到最后一行了,结束
            //生成地图
            res.emplace_back(cur);
            return;
        }
        //只需要遍历当前行所有的列,寻找可用位置
        for(int col=0;col<n;++col){
            if(!isValid(row,col,n)){//这个位置不可以选择
                continue;
            }
            //选择col,生成当前行 (一开始打算每次生成当前行,后面发现不需要这么麻烦,全初始化再改一个点比较好)
            // string line="";
            // for(int i=0;i<n;i++){
            //     line+=(i==col)?"Q":".";
            // }
            cur[row][col]='Q';
            // cur.emplace_back(line);
            work(n,row+1);
            // cur.pop_back();  
            cur[row][col]='.';          
        }
    }
    vector<vector<string>> solveNQueens(int n) {
        //当前图默认全.
        for(int i=0;i<n;++i){
            string line="";
            for(int j=0;j<n;++j){
                line+=".";
            }
            cur.emplace_back(line);
        }
        work(n,0);
        return res;
    }
};