关于八皇后问题的解答

对于这个八皇后问题,两个月前把我难为的,如今复习到数据结构树这一章,我又见到了这个所谓的八皇后问题,决定要把它解决掉!


在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上。问共有多少种不同的方法,并且指出各种不同的放法。

【算法思路】

  第一步:不考虑约束条件,每个皇后放法都有八种方式去放,也就构成了一个完整八叉树。

  第二步:对这个八叉树进行遍历,对不符合要求的树进行截枝,留下来的就是可行的方案。

最重要的地方:解空间的构建,这个八皇后问题可以用一个一维数组,x[i],来表示,i表示第几行,x[i]表示第几位置。于是我们考虑第一个条件,不能再同一行,同一列于是我们得到x[i]不能相同。剩下一个条件是不能位于对角线上,这个条件不是很明显,我们经过分析得到,设两个不同的皇后分别在j,k行上,x[j],x[k]分别表示在j,k行的那一列上。那么不在同一对角线的条件可以写为abs((j-k))!=abs(x[j]-x[k]),其中abs为求绝对值的函数。

递归方式:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;


static int num;
static int *x;
static int sum;

bool place(int k)
{
    for(int j = 1;j<k;j++)
        if(abs(x[k] - x[j]) == abs(k-j)||x[j] == x[k])
            return false;
        return true;

}

void backtrack(int t)
{
    if(t>num) //num为皇后的数目
    {
        sum++;//sum为所有的可行的解
        for(int m = 1;m<num;m++)
        {
            cout<<x[m];//这一行用输出当递归到叶节点的时候,一个可行解
        }
        cout<<endl;
    }
    else
        for(int i = 1;i<=num;i++)
        {
            x[t] = i;
            if(place(t)) backtrack(t+1);//此处的place函数用来进行我们上面所说的条件的判断,如果成立,进入下一级递归
        }
}




int main()
{
    num = 8;
    sum = 0;
    x = new int[num+1];
    for(int i= 0;i<=num;i++)
        x[i] = 0;
    backtrack(1);
    cout<<"方案共有"<<sum;


}

解题法二:

#include <iostream>


using namespace std;


static int tot=0;


void search_q(int cur,int* p,int n)
{
    int i,j;
    if(cur==n)
    {
        tot++;
        cout<<tot<<":";
        for(i=0;i<n;i++)
            cout<<p[i];
        cout<<endl;
    }
    else for(i=0;i<n;i++)
    {
        int ok=1;
        p[cur]=i;
        for(j=0;j<cur;j++)
        {
            if(p[cur]==p[j]||p[cur]+cur==p[j]+j||p[cur]-cur==p[j]-j)
            {
                ok=0;
                break;
            }
        }
        if(ok)   search_q(cur+1,p,n);
    }
}
int main()
{
    int arr[8][8];
    int c[8];
    search_q(0,c,8);


    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值