八皇后算法分析及源代码

[问题描述]  

八皇后问题是一个古老而著名的问题是回溯算法的典型例题。该问题是十九 世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使 其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上, 问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作 者发表了40种不同的解,后来有人用图论的方法解出92种结果。

[需求分析]

这个问题包括了行,列,两条对角线;

列:规定每一列放一个皇后,不会造成列上的冲突;

行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;

1.输入

W,N W1,V1 W2,V2 ......

2.输出

纵向排序输出

3.测试数据

 10,3 3,4 4,5 5,6

 [概要设计]

1.解决冲突问题: 

这个问题包括了行,列,两条对角线;

列:规定每一列放一个皇后,不会造成列上的冲突;

行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;

对角线:对角线有两个方向。在这我把这两条对角线称为:主对角线和从对角线。在同一对角线上的所有点(设下标为(i,j)),要么(i+j)是常数,要么(i-j)是常数。因此,当第I个皇后占领了第J列后,要同时把以(i+j)(i-j)为下标的标记置为被占领状态。

2.数据结构的实现

而对于数据结构的实现,学生则是着重于:

数组a[I]a [I]表示第I个皇后放置的列;I的范围:1..8;

对角线数组:b[j](主对角线),c[j](从对角线),根据程序的运行,去决定主从对角线是否放入皇后;

1 .数据初始化。

2 2 .n列开始摆放第n个皇后(因为这样便可以符合每一竖列一个皇后的要求),先测试当前位置(nm)是否等于0(未被占领)。如果是,摆放第n个皇后,并宣布占领(记得姚横列竖列斜列一起设置),接着进行递归;如果不是,测试下一个位置(nm+1),但是如果当n<=8m=8时,发现此时已无法摆放时,便要进行回溯。从问题的某一种可能出发,搜索从这种情况能出发,继续搜索,这种不断回溯的寻找解的方法,称为回溯法

3.使用数组实现回溯法的思想。

4.n>8时,便打印出结果。

5.输出函数我使用printf输出,运行形式为:第m种方法为:* * * * * * * *

[完整程序]

#include <conio.h>

#include <math.h>

#include <stdlib.h>

#include <stdio.h>

#include <iostream.h>

#define QUEENS 8

int iCount = 0;  //!记录解的序号的全局变量。

int Site[QUEENS];   //!记录皇后在各行上的放置位置的全局数组。

void Queen(int n); //!递归求解的函数。

void Output();//!输出一个解。

int IsValid(int n);

//!判断第n个皇后放上去之后,是否有〉冲突。

void main() /*----------------------------Main:主函数。----------------------------*/

{

system("title 叶青--递归算法八皇后问题 ");

cout << "                    " << "八皇后的解法:" << endl;

cout << "        " << "-------------------------------------" << endl;

Queen(0);  //!从第0行开始递归试探。   

getch();//!按任意键返回。

}

void Queen(int n)   /*-----------------Queen:递归放置第n个皇后,程序的核心!----------------*/

{

int i;

if (n == QUEENS)  //!参数n0开始,等于8时便试出了一个解,将它输出并回溯。

{

Output();        return;

}

for (i = 1; i <= QUEENS; i++)  //!n还没到8,在第n行的各个行上依次试探。   

{

Site[n] = i;  //!在该行的第i行上放置皇后。       

if (IsValid(n))   //!如果放置没有冲突,就开始下一行的试探。          

Queen(n + 1);

}

}

int IsValid(int n) /*------IsValid:判断第n个皇后放上去之后,是否合法,即是否无冲突。------*/

{

int i;

for (i = 0; i < n; i++)  //!将第n个皇后的位置依次于前面n1个皇后的位置比较。  

{

if (Site[i] == Site[n])  //!两个皇后在同一列上,返回0。    

return 0;

if (abs(Site[i] - Site[n]) == (n - i))  //!两个皇后在同一对角线上,返回0。       

return 0;

}

return 1; //!没有冲突,返回1

}

void Output()/*------------Output:输出一个解,即一种没有冲突的放置方案。------------*/

{

int i;

printf("No.%-5d", ++iCount); //!输出序号。  

for (i = 0; i < QUEENS; i++)//!依次输出各个行上的皇后的位置,即所在的列数。      

printf("%d ", Site[i]);

printf("\n");

}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值