八皇后问题

    回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。

    对于n后问题的任何一个解而言,每一个皇后在棋盘上的位置无任何规律,不具有系统性,而更象是随机放置的。由此容易想到下面的拉斯维加斯算法。 与蒙特卡罗算法类似,拉斯维加斯算法找到正确解的概率随着它所用的计算时间的增加而提高。对于所求解问题的任一实例,用同一拉斯维加斯算法反复对该实例求解足够多次,可使求解失败的概率任意小。拉斯维加斯算法的一个显著特征是它所作的随机性决策有可能导致算法找不到所需的解。

    在棋盘上相继的各行中随机地放置皇后,并注意使新放置的皇后与已放置的皇后互不攻击,直至n个皇后均已相容地放置好,或已没有下一个皇后的可放置位置时为止。

     n后问题

     问题描速:在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。

     四皇后问题

    这个问题要求在一个4X4的棋盘上放上4个皇后,使得每一个皇后既攻击不到另外三个皇后,也不被另外三个皇后所攻击。按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子。因此,四后问题等于要求四个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。

我们给4×4棋盘的行和列分别从左到右和从上到下编号为1234,同时也给四个皇后也分别编为1234。由于要求不同的皇后不能放在同一行,不失广般性,可设皇后i只放在第i行。这样,四后问题的解可用4元组(x1x2x3x4)来表示。其中xi表示皇后i所处的列的列号。因此,四后问题相应的

     E={(x1,x2,x3,x4) ∣xi∈Si i=l,2,3,4}

   Si={1,2,3,4}  1≤i≤4。


    四后问题相应的约束集D包含如下的约束:

    ①xi≠xj(皇后i和j不在同一列上);

    ② xi −i≠ xj− j(皇后i和j不在斜率为-l的同一条斜线上);

    ③ xi+i≠ xj+j (皇后i和j不在斜率为+l的同一条斜线上);

    ④ 其中i、j=1,2,…,k,且i<>j。从这些约束的几何含义便可断定D具有完备性。

   四后问题相应的状态空间树是一棵满四叉树 。

conio.h不是C标准库中的头文件,在C standard library,ISO C 和POSIX标准中均没有定义。

conio是Console Input/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等。

八皇后实现代码

// SQUEEN12.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <stdlib.h>
#include<conio.h>//Console Input/Output(控制台输入输出)的简写,getch()函数
#include<iostream>
using namespace std;


//用queens[]数组储存每个皇后的位置


#define  Max 8
int sum = 0;


class QueenPuzzle
{


    int queens[Max];
public:
    void printout();
    int  IsVaild(int n);//判断第n个皇后放上去以后,是否合法
    void PlaceQueen(int i);
};


void QueenPuzzle::printout()
{
for (int i=0;i<Max;i++)
{
     for (int j=0;j<Max;j++)
     {
         if (j==queens[i])
             cout<<"■";
         else
             cout<<"□";


     }
     cout<<endl;


}


    cout<<"按q键退出,按其他键继续"<<endl<<endl;
     if(getch()=='q')//从键盘上获得q
         exit(0);


}


void QueenPuzzle::PlaceQueen(int i)
{


    for(int j=0;j<Max;j++)
        //如果全部放完输出结果;
    {
        if (i==Max)
        {
            sum++;
            cout<<"第"<<sum<<"组解"<<endl;
            printout();
            return;
        }


        //放置皇后
        queens[i] = j;
       //判断下一位置能放皇后不
        if (IsVaild(i))
        {
            PlaceQueen(i+1);
        }
    
    }
}


//判断皇后放上去是否合法,是否无冲突
int QueenPuzzle::IsVaild(int n)
{
  //将第n个皇后与第n+1个皇后进行比较
   for (int i=0;i<n;i++)
   {
     if (queens[i]==queens[n])//是否是同一列
         return 0;
     if(abs(queens[i]-queens[n])==(n-i))//是否在同一条对角线 
         return 0;


   }


   return 1;
  
}


int  main()
{
QueenPuzzle queen;
queen.PlaceQueen(0);//给PlaceQueen(i)中的i初始赋值 0
cout<<"共有"<<sum<<"组解"<<endl;


    return 0;
}











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
二、 算思想: 采用回溯解决八皇后问题。从第一行开始,放第一个皇后,放好皇后以后,她所在的行,列和对角线上的每一个位置就是她的管辖范围,别的皇后没有权利干涉,否则死无藏身之地。 然后,第二个皇后,从第二行的第一列开始判断所在的位置是否是别的皇后的管辖范围,找到第一个还没有被占据的位置,则将其占为己有。暂时,该皇后停在该位置。然后,第三个到第八个皇后依次从第三行,第四行,… ,到第八行的第一列开始寻求自己的位置。假如到第i个皇后时,已经没有任何位置可选,则第i-1个皇后必须往后移动进行协调,同样,假如第i-1个皇后往后移动时没有找到空位置,则第i-2个皇后必须往后移动,进行协调,当找到空位置时,暂时停下,将下一个皇后重新从第一列开始寻找空位置。重复上述过程,直到所有皇后都停下来。则得到了第一个解。要想产生所有的解,则当产生第一个解以后,第八个皇后往后移动,找下一个可以利用的空位置,找不到,则第七个皇后必须往后移动,若找到空位置则停下,第八个皇后从第八行第一列重新试探,找到空位置。一直这样,直到第一个皇后将第一行遍历完。得到的解就是所有解。 三、 概要设计: ***************类型及相关变量定义***************** //位置信息类型 typedef struct { int row; int col; }PosType; //皇后类型 typedef struct Queen{ PosType pos; int number; //第几号皇后 }QueenType; //栈节点类型 typedef struct Note{ QueenType queen; struct Note *next; }NoteType; //棋盘,某一位置chessboard[i][j]上有皇后,则该位的值变为皇后序号。同样,该皇后的势 //力范围内的位置上的值全部变为该皇后的序号。 int chessboard[8][8]; //结果集,共92种解,每一种解中记录8个位置信息。 PosType ResultSet[92][8]; //定义一个栈,保存信息 Typedef struct{ NoteType head; Int size; }QueenStack; //定义一个栈,存放皇后信息 QueenStack qstack; *************相关操作**************** //初始化棋盘,开始时每个位置上都没有皇后,值全为0;并给8个皇后编号。 void initChessboard(); //回溯求八皇后问题的所有解,皇后协调算 void queenCoordinate(); //输出所有解 void printResult();

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值