回溯——N皇后问题

1.问题分析

在n X n的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之同一行,同一列,同一写线上的棋子。现在n X n的棋盘上放置n个皇后,使彼此不受攻击。

如图所示,我们要在i行j列放置一个皇后,那么第i行的其他位置(同行),j列其他位置(同列),同一写线上的其他为止吗,都不能放置皇后。

条件是这么要求的,但是我们也不能杂乱无章的尝试每个为止,我们可以以行为主导:

  • 在第一行第一列放置一个皇后。
  • 在第二行放置第二个皇后,第二个皇后的位置不能跟第一个皇后同一行同一列同一条写线上·,这里不用再判断同行,因为这里本来就不同行。
  • 第三行……
  • 第四行……
  • 以此类推。

2.算法设计

(1)定义问题i解空间。

(2)解空间的组织结构:是一颗m叉树。

(3)搜索空间

约束条件:在第t行放置第t个皇后时,第t个皇后的位置不能和前t-1个皇后同列,同斜线。第i个皇后和第j个皇后不同列,即 xi !=xj,并且不同斜线:|i-j| !=| xi - xj |。

搜索过程:从根开始,以深度优先搜索的方式进行搜索。根结点是活结点,并且是当前的扩展结点。在搜索过程中,当前的扩展结点沿纵深方向移向一个新结点,判断该结点是否满足约束条件。如果满足,该新结点成为活结点,并且成为当前的活结点,继续向下搜索。如果不满足,换到新的结点的兄弟结点继续搜索。如果新结点没有兄弟结点,或者兄弟结点已经全部搜索完毕,则扩展结点成为死结点,搜索回溯到其父结点处继续进行。搜索过程直到找到问题的根结点变成死结点为止。

3.源代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=111;
int n;
int x[N];
int countn;

bool OK(int t)
{
    bool ok=true;
    for(int j=1;j<t;j++)
    {
        if(x[t]==x[j] || (t-j) ==fabs(x[t]-x[j]) )//约束条件
        {
           ok=false;
           break;
        }
    }
    return ok;
}

void backtrack(int t)
{
    if(t>n)
    {
        countn++;
        for (int i=1;i<=n;i++)
        {
            cout << x[i] << "   ";
        }
        cout << endl;
        cout << "——————" << endl;
        cout << endl;
    }
    else
    {
        for (int i=1;i<=n;i++)
        {
            x[t]=i;
            if(OK(t))
            {
                backtrack(t+1);
            }
        }
    }
}

int main()
{
    cout << "请输入皇后的个数" << endl;
    cin >> n;
    countn=0;
    backtrack(1);
    cout << "答案的个数是:"<< countn << endl;
    return 0;
}

4.测试结果

发布了57 篇原创文章 · 获赞 9 · 访问量 3608

猜你喜欢

转载自blog.csdn.net/Jayphone17/article/details/102964195
今日推荐