八皇后问题Checker Challenge(C++)

  第一次接触深度优先搜索qwq,小白第一次发文

洛谷题目,原文如下

    

        该题可以看成:每行都有一个棋子,但是每行的棋子它所在的列和它所处对角线上没有其他棋子。

        问题难点在于当我们放下第一个,接着放下一个的时候,怎么判断第一个位置对接下来放的棋子的影响。

定义 全局变量total为问题解的个数

先写输出函数(问题分成一个个小块)

题目要求我们输出前三个  每次运行print时total都会计数一次,当total小于3时,顺便输出解的情况

void print()
{
    if(total<3)
    {
        for(int i=1; i<=n; i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    total++;
}

 下面开始是本题难点了

        不妨从上往下看,即从第一行往下摆。

于是可以用一个循环表示从上往下摆,

写函数,queen中i为第i个皇后,或者理解成第i行。

循环j为第j列,从左往右依次试着放下皇后。满足所在列为0(即这一列没有被其他皇后占了位置)(下同)&&主对角线为0&&副对角线为0,即可放下,同时标记,然后摆下一行。

void queen(int i)
{
    for(int j=1; j<=n; j++)
    {
        if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))
        {
            a[i]=j;
            b[j]=1;
            c[i+j]=1;
            d[i-j+n]=1;//标记
            queen(i+1);
        }
    }
}

 数组b为列,c为主对角线,d为副对角线,为啥是c为i+j,d为i-j+n呢?

下图为主对角线表示i+j的结果和副对角线i-j的结果。

 

 然鹅,我们发现i-j<0,所以加n整体都扩大,并不会影响我们判断的。

 然后,当i>n时,表明最后一个皇后已经放下了(没有多余的皇后了,呜呜呜,太不容易了QAQ)

我们需要加个判断语句,打印出这种做法。

void queen(int i)
{
    if(i>n)
    {
        print();
        return;
    }
    else
    {
        for(int j=1; j<=n; j++)
        {
            if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))
            {
                a[i]=j;
                b[j]=1;
                c[i+j]=1;
                d[i-j+n]=1;//标记
                queen(i+1);
            }
        }
    }
}

 是不是就这样结束了?大漏特漏!!!

我们在每次放完一组解的时候要把标记数组(b,c,d)清除干净,放在循环里面就行了。

所以完整的函数代码如下:

void queen(int i)
{
    if(i>n)
    {
        print();
        return;
    }
    else
    {
        for(int j=1; j<=n; j++)
        {
            if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))
            {
                a[i]=j;
                b[j]=1;
                c[i+j]=1;
                d[i-j+n]=1;
                queen(i+1);
                b[j]=0;
                c[i+j]=0;
                d[i-j+n]=0;
            }
        }
    }
}

 

AC完整代码如下

#include <iostream>
using namespace std;
int n,total;
int a[100],b[100],c[100],d[100];
void print()
{
    if(total<3)
    {
        for(int i=1; i<=n; i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    total++;
}
void queen(int i)
{
    if(i>n)
    {
        print();
        return;
    }
    else
    {
        for(int j=1; j<=n; j++)
        {
            if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))
            {
                a[i]=j;
                b[j]=1;
                c[i+j]=1;
                d[i-j+n]=1;
                queen(i+1);
                b[j]=0;
                c[i+j]=0;
                d[i-j+n]=0;
            }
        }
    }
}

int main()
{
    cin>>n;
    queen(1);
    cout<<total;
    return 0;//好习惯从我做起
}

 刚接触算法,请各位大佬批评指正QAQ

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值