Acwing843、Leetcode051(n-皇后问题)--------DFS(全排列)

本文解析了N皇后问题的解决思路,通过回溯算法逐行尝试在国际象棋棋盘上放置皇后,同时介绍了两种不同的代码实现,包括一个使用C++和矩阵记录状态,另一个使用C++的面向对象编程。讨论了剪枝技巧以减少搜索空间。
摘要由CSDN通过智能技术生成

地址:

描述:

思路:

代码:

回溯(剪枝)思路:

 Leetcode

一个个遍历


地址:

https://www.acwing.com/problem/content/845/

https://leetcode-cn.com/problems/n-queens/

描述:

 

思路:

整体的思路:我们要枚举每一行的皇后应该放在第几列上

其实和全排列的思想非常类似

代码:

回溯(剪枝)思路:

#include <iostream>
using namespace std;
int n;
//1<=n<=9
const int N=10;
char qi[N][N];
//分别记录的是该位置的列,正对角线,斜对角线上是否放过皇后,若均没有皇后,填入皇后,并递归到下一行
//为什么正对角和反对角要2*N,因为列只有N条,而对角线有2*N条
bool lie[N],z[2*N],f[2*N];
//当前枚举的是第x行的Q应该放在第y列?
void dfs(int x){
    //此时Q已经全部放完
    if(x==n){
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
                cout << qi[i][j];
            cout << endl;
        }
        cout << endl;
        return;
    }
    //y表示第y列
    for(int y=0;y<n;y++){
        //x-y+n和x+y怎么得来的见图解
        if(!lie[y]&&!z[x-y+n]&&!f[x+y]){
            lie[y]=z[x-y+n]=f[x+y]=true;
            //要是它的同一条列,正对角和反对角都没有皇后,那么就在第x行第y列放上皇后
            qi[x][y]='Q';
            //递归去求下一行
            dfs(x+1);
            //回溯
            lie[y]=z[x-y+n]=f[x+y]=false;
            qi[x][y]='.';
        }
    }
}
int main(){
    cin>>n;
    //初始化棋盘
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            qi[i][j]='.';
        }
    }
    dfs(0);
    return 0;
}

 Leetcode

class Solution {
public:
    int n;
    vector<bool> lie,z,f;
    vector<vector<string>> ans;
    vector <string> temp;
    vector<vector<string>> solveNQueens(int _n) {
    n=_n;
    lie=vector<bool>(n);
    z=f=vector<bool>(2*n);
    temp=vector<string> (n,string(n,'.'));
    dfs(0);
    return ans;
    }
    void dfs(int x){
        if(x==n){
            ans.push_back(temp);
            return ;
        }
        for(int y=0;y<n;y++){
            if(!lie[y]&&!z[x+y]&&!f[x-y+n]){
                lie[y]=z[x+y]=f[x-y+n]=true;
                temp[x][y]='Q';
                dfs(x+1);
                temp[x][y]='.';
                lie[y]=z[x+y]=f[x-y+n]=false;
            }

        }
    }
};

一个个遍历

#include <iostream>
using namespace std;
int n;
//1<=n<=9
const int N=10;
char qi[N][N];
//分别记录的是该位置的行,列,正对角线,斜对角线上是否放过皇后,若均没有皇后,填入皇后,并递归到下一行
//为什么正对角和反对角要2*N,因为列只有N条,而对角线有2*N条
bool hang[N],lie[N],z[2*N],f[2*N];
//整体思路:一个一个看是否要放皇后
//num记录已经放下的皇后数量
void dfs(int x,int y,int num){
    //这一行的皇后放完了
    if(y==n) {
        //转到下一行,开始遍历
        y=0;
        x++;
    }
    if(x==n){
        if(num==n){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    cout<<qi[i][j];
                }//for(j)
                cout<<endl;
            }//for(i)
        cout<<endl;
        }
        return ;
    }
    //不放皇后
    dfs(x,y+1,num);
    //放皇后
    if(!hang[x]&&!lie[y]&&!z[x-y+n]&&!f[x+y]){
        hang[x]=lie[y]=z[x-y+n]=f[x+y]=true;
        qi[x][y]='Q';
        //写成dfs(x+1,0,nums+1)也可以
        dfs(x,y+1,num+1);
        hang[x]=lie[y]=z[x-y+n]=f[x+y]=false;
        qi[x][y]='.';
    }
}
int main(){
    cin>>n;
    //初始化棋盘
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            qi[i][j]='.';
        }
    }
    dfs(0,0,0);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值