“八皇后”问题——回溯+深搜

八皇后问题是一个经典的回溯算法问题,目标是在8x8的棋盘上放置8个皇后,使得任何两个皇后之间都不存在威胁(即任何两个皇后都不能在同一行、同一列或同一斜线上)。

1、理思路

        由于皇后的位置特殊性导致如果通过常规算法会带来的时间复杂度的提高,不妨看以下思路:

        行为i,列为j,每个单元格对应为(i+j),再通过寻找从左上到右下的对角线表达式为

(j-i-2*8);

012345678
123456789
2345678910-9
34567891011-10
456789101112-11
5678910111213-12
67891011121314-13
789101112131415-14
8910111213141516-15
-23-22-21-20-19-18-17-16

同时从右上到左下的对角线表达式为(i+j);

可得代码思路。

2、写代码

#include <bits/stdc++.h>
using namespace std;
int a[50],b[50],c[50],n;
char ans[10][10];
bool f()
{
    for(int i=1;i<=8;i++)
    {
        
        if(a[i]==0) return 0;
    }
    return 1;
}
void dfs(int i)
{
    for(int j=1;j<=8;j++)
    {
        if(a[j]==0&&b[i+j]==0&&c[(j-i-2*8)*(-1)]==0)
        {
            if(i==8)
            {
                a[j]=1;
                if(f()==0) return;
                cout<<"Situation "<<(++n)<<":"<<endl;
                ans[i][j]='Q';
                for(int x=1;x<=8;x++)
                {
                    for(int y=1;y<=8;y++)
                    {
                        cout<<ans[x][y];
                    }
                    cout<<endl;
                }
                a[j]=0;
                ans[i][j]='.';
                cout<<endl;
                return;
            }
            a[j]=1;
            b[i+j]=1;
            c[(j-i-2*8)*(-1)]=1;
            ans[i][j]='Q';
            dfs(i+1);
            a[j]=0;
            b[i+j]=0;
            c[(j-i-2*8)*(-1)]=0;
            ans[i][j]='.';
        }
    }
}
int main()
{
    for(int i=1;i<=8;i++)
    {
        for(int j=1;j<=8;j++)
        {
            ans[i][j]='.';
        }
    }
    dfs(1);
    return 0;
}

3、结果

解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。

4、拓展

当然随便改一下便可变成“m皇后”问题(m的范围不给出了)

#include <bits/stdc++.h>
using namespace std;
int a[500],b[500],c[500],n,m;
char ans[200][200];
bool f()
{
    for(int i=1;i<=m;i++)
    {
        
        if(a[i]==0) return 0;
    }
    return 1;
}
void dfs(int i)
{
    for(int j=1;j<=m;j++)
    {
        if(a[j]==0&&b[i+j]==0&&c[(j-i-2*m)*(-1)]==0)
        {
            if(i==m)
            {
                a[j]=1;
                if(f()==0) return;
                cout<<"Situation "<<(++n)<<":"<<endl;
                ans[i][j]='Q';
                for(int x=1;x<=m;x++)
                {
                    for(int y=1;y<=m;y++)
                    {
                        cout<<ans[x][y];
                    }
                    cout<<endl;
                }
                a[j]=0;
                ans[i][j]='.';
                cout<<endl;
                return;
            }
            a[j]=1;
            b[i+j]=1;
            c[(j-i-2*m)*(-1)]=1;
            ans[i][j]='Q';
            dfs(i+1);
            a[j]=0;
            b[i+j]=0;
            c[(j-i-2*m)*(-1)]=0;
            ans[i][j]='.';
        }
    }
}
int main()
{
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=m;j++)
        {
            ans[i][j]='.';
        }
    }
    dfs(1);
    return 0;
}

感谢观看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值