N皇后问题

本文介绍了如何运用回溯算法解决n皇后问题,即在n×n的棋盘上放置n个皇后,确保它们不会互相攻击。通过递归和判断落点函数,实现了皇后安全放置并返回所有可能的解决方案。
摘要由CSDN通过智能技术生成

目录

题干

回溯算法

判断落点

整体代码


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

题干

在国际象棋中,即将n个棋子放到n*n的棋盘上,使得每个棋子不能同行,不能同列,不能同斜线。

回溯算法

回溯算法实际上是穷举所有的可能性,在这个规则中,我们可以发现由于每一行只能有一个棋子,我们可以逐层确定棋子的位置,每一个棋子是否能落下再由前面的棋子落点确定。

回溯部分代码如下:
 

void backtracking(int row,int n,vector<string>& chess)
{
    //先确定终止条件
    if(n==row)
    {
        result.push_back(chess);
    }
    for(int i=0;i<chess[0].size();i++)
        {
            //判断落点是否合适
            if(IsVaild(row,i,chess))
            {
                chess[n][i]='Q';
                //进入下层
                backtracking(row+1,n,chess);
                //回溯
                chess[n][i]='.';
            }
            else
            {
                continue;
            }
        }
}

row是目前所在行,n是所给的棋盘n*n大小,在每一层递归中,我们确定一层的'Q',在向下一层,如果某一层没有一个棋子可以落下,则回溯,并将上一层的'Q'向后移一位。

判断落点

只需要在竖向,两条斜向上判断,且只需要判断落点上方的情况。

bool IsVaild(int x,int y,vector<string> chess)
{
    //竖向
    for(int i=x-1;i>=0;i--)
        {
          if(chess[i][y]=='Q')
          {
              return false;
          }
        }
    //斜向上两条
    for(int i=x-1.j=y-1;i>=0,j>=0;i--,j--)
        {
            if(chess[i][j]=='Q';)
            {
                return false;
            }
        }
        for(int i=x-1.j=y+1;i>=0,j<chess[0].size();i--,j++)
        {
            if(chess[i][j]=='Q';)
            {
                return false;
            }
        }
}

整体代码

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class solution
{
private:
vector<vector<string>> result;
void backtracking(int row,int n,vector<string> chessboard)
{
    if(row==n)
    {
        result.push_back(chessboard);
        return;
    }
    for(int i=0;i<n;i++)
    {
        if(IsVaild(row, i, n, chessboard))
        {
            chessboard[row][i]='Q';
            backtracking(row+1, n, chessboard);
            chessboard[row][i]='.';
        }
        else 
        {
            continue;
        }
    }
}
bool IsVaild(int x/*row*/,int y,int n,vector<string>& chessboard)
{
    for(int i=x;i>=0;i--)
    {
        if(chessboard[i][y]=='Q')
        {
            return false;
        }
    }
    for(int ix=x-1,iy=y-1;ix>=0&&iy>=0;ix--,iy--)
    {
        if(chessboard[ix][iy]=='Q')
        {
            return false;
        }

    }
    for(int ix=x-1,iy=y+1;ix>=0&&iy<n;ix--,iy++)
    {
        if(chessboard[ix][iy]=='Q')
        {
            return false;
        }

    }
    return true;
}
public:
vector<vector<string>> results(int n)
{
    result.clear();
    vector<string> chessboard(n,string(n,'.'));
    backtracking(0, n, chessboard);
    return result;
}

};

int main() {
    std::cout << "Hello World!\n";
    solution so;
    int m=5;
    for(auto i:so.results(m))
    {
        for(auto j:i)
        {
            for(auto k:j)
            {
                cout<<k<<' ';
            }
            cout<<endl;
        }
        cout<<"--------------------- --"<<endl;
    }
    cout<<so.results(m).size()<<endl;

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值