LeetCode—笔记—51、N皇后——递归回溯,个人思路,简单易懂

LeetCode—笔记—51、N皇后——递归回溯,个人思路,简单易懂

51. N 皇后

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

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

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

image-20210411163336134.png)]

一、题目分析

根据题目意思是就是N*N的矩形棋盘上,放置N枚棋子,每行一个,每列一个,每斜线一个;

二、解题思路

我们可以这样想,以4*4为例:

1、在每行依次放置棋子,但每次只能放置一枚,如第一行:分别在0,1,2,3列放置一枚棋子,第二行再从0,1,2,3列放置一枚棋子,以此类推;

2、放置每一枚棋子后总棋子数目减一;

3、放置棋子时判断是否满足题目要求,如果满足进行下一行放置,不满足遍历下一次位置。

4、采用递归的方法放置每一行

5、怎么判断放置的棋子是否在之前的棋子的列上与斜线上?第三节解释

三、代码撰写思路及其细节

怎么判断放置的棋子是否在之前的棋子的列上与斜线上?

因为采用每行放置的方式所以不用考虑行重复,每次放置时纪录本行放置的列的位置,数组为addr_row_col_[n];然后判断是否在同一列,就很简单,遍历数组判断col==addr_row_col_[i];即可。那么怎么判断斜线呢,也很简单,就是
c o l = = a d d r _ r o w _ c o l _ [ i ] − ( r o w − i ) ; c o l = = a d d r _ r o w _ c o l _ [ i ] + ( r o w − i ) ; col==addr\_row\_col\_[i]-(row-i);\\ col==addr\_row\_col\_[i]+(row-i);\\ col==addr_row_col_[i](rowi);col==addr_row_col_[i]+(rowi);
不明白可以动手画一画。

然后代码里的注释都是本人遇到错误的一些小细节。

class Solution {
public:
    void solve_n(vector<vector<string>>&_s,vector<string> & _ss,string & _sss,int _row,int _col,int Leftover,int addr_row_col_[]){//Leftover 剩余棋子
        if(Leftover==0){//剩余棋子为零返回
            _s.push_back(_ss);
            //cout<<"*   *"<<endl;
            return;
        }
        //cout<<Leftover<<endl;
        bool b=false;
        while(_col<(_row+Leftover)){
                                    //判断在addr_row_col_中是否存在,同时判断是否在上一行addr_row_col_[_row-1]的对角线
                                    //不仅上一行的对角线是所有的对角线
                                    //注意递归后恢复此次addr_row_col_里的数值,这个很重要!!!!!!!
                                    //递归后的回溯一定要将某些数值恢复默认值此处还有一个 _col++超过边界string不会报错,然后_sss[Q]
                                    //不会报错,但这是不符合要求的,所以if(_col==_row+Leftover) break;
            _col++;
            for(int j=0;j<=_row;j++){//只用判断前N行放置的结果
                if(_col==addr_row_col_[j]-(_row-j)||_col==addr_row_col_[j]+_row-j){
                     b=true;
                     break;
                }
                if(_col==addr_row_col_[j]){
                    b=true;
                    break;
                } 
            }
            if(b) {
                b=false;
                continue;
            }
            if(_col==_row+Leftover) break;//放置位置虽然满足条件,但_col在棋盘外
            addr_row_col_[_row]=_col;//纪录每一行col位置
            _sss[_col]='Q';//修改字符串
            //cout<<_col<<"     "<<_sss<<endl;
            _ss.push_back(_sss);//末尾添加字符串
            _sss[_col]='.';//改回棋盘
            solve_n(_s,_ss,_sss,_row+1,-1,Leftover-1,addr_row_col_);//假设初始棋子位置位与—1列
            addr_row_col_[_row]=-2;//恢复此时位置的addr_row_col_
            _ss.pop_back();//弹出此时添加的行
        }
        return;
        
    }
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> s;
        vector<string> ss;
        string sss;
        int row=0; //行
        //int col=-1; //列
        int addr_row_col[n];
        for(int i=0;i<n;++i){
            sss.push_back('.');//初始化sss字符串
            addr_row_col[i]=-2;//初始化放置位置,负数即可
        }
        solve_n(s,ss,sss,row,-1,n,addr_row_col);//递归——回溯,假设初始棋子位置位与—1列
        return s;
    }
};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I4HKhrBk-1618132032456)(C:\Users\wei\AppData\Roaming\Typora\typora-user-images\image-20210411164417853.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值