八皇后问题的解决完整文档

合集下载

八皇后问题详细的解法

八皇后问题详细的解法

若无法放下皇后则回到上一行, 即回溯
当n行的皇后都已确定后,我们 就找到了一种方案
check2 (int a[ ],int n)
queen21(例) 1 b加约束的枚举算法{//i多nt次i; 被调用,只是一重循环
{int a[9]; for (a[1]=1;a[1]<=8;a[1]++) for (a[2]=1;a[2]<=8;a[2]++)
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i+nt(a[i]); }
题,而不能解决任意
}}}}}}}
的n皇后问题。
18
2 回溯法应用-算法说明
按什么顺序去搜? 目标是没有漏网之鱼,尽量速度快。
5
2 【问题设计】盲目的枚举算法
a 盲目的枚举算法
通过8重循环模拟搜索空间中的88个状态;
按枚举思想,以DFS的方式,从第1个皇后在第1列开 始搜索,枚举出所有的“解状态”:
从中找出满足约束条件的“答案状态”。

八皇后问题实验报告

八皇后问题实验报告

实验报告——八皇后问题求解(递归和非递归)学号:专业年级:姓名:一、需求分析(要实现的功能描述)1.问题描述八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。

当且仅当n=1或n≥4时问题有解。

八皇后问题最早是由国际国际象棋棋手马克斯·贝瑟尔于1848年提出。

诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。

2.实现功能八皇后问题实现了在棋盘上摆放八个皇后的功能,这八个皇后任意两个皇后都不能处于同一条横行、纵行或斜线上。

3.测试数据测试数据可以通过手工寻找三组满足需要的值,测试数组(M,N),其中M代表皇后所在的行,N代表皇后所在的列。

例如,第一组测试数据:(1,4)、(2,7)、(3,3)、(4、8)、(5,2)、(6,5)、(7,1)、(8,6);第二组测试数据(1,4)、(2,2)、(3,7)、(4,3)、(5,6)、(6,8)、(7,5)、(8,1)。

最后与编程求得的结果进行比较。

如果这三组数据在最后编程求得的结果中,说明程序的编写基本没有什么问题。

二、概要设计在进行概要设计的过程中,要清楚整个程序包含的功能模块及模块间的调用关系。

对于八皇后问题,整个程序中应该包括主函数模块,摆放皇后的函数模块,以及判断皇后的位置是否摆放正确的判断模块。

对于模块间的关系,在运行主函数的过程中会调用摆放皇后的函数模块,在摆放皇后的函数模块中,又会调用判断皇后位置是否摆放正确的判断模块。

三、详细设计抽象数据类型中定义的各种操作算法实现(用N-S图描述)对于求解八皇后问题的非递归算法,N-S图如下:对于八皇后问题求解的递归算法,N-S图如下:四、调试分析1.程序在调式过程中出现的问题及解决方法由于对于C语言编程问题掌握的并非十分熟练,因而在程序的调试过程中出现了一些问题。

八皇后问题的解决完整

八皇后问题的解决完整

八皇后问题的解决完整 Standardization of sany group #QS8QHH-HHGX8Q8-GNHHJ8-HHMHGN#淮阴工学院数据结构课程设计报告设计题目:八皇后2008 年 6 月 25 日设计任务书摘要:八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。

而本课程设计本人的目的也是通过用c++语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.使用递归方法最终将其问题变得一目了然,更加易懂。

关键词:八皇后 ; c++ ; 递归法目录.1. 课题综述1. 1课题的来源及意义八皇后问题是一个古老而着名的问题,该问题是十九世纪着名的数学家高斯1850年提出的。

在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。

所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。

到了现代,随着计算机技术的飞速发展,这一古老而有趣的数学游戏问题也自然而然的被搬到了计算机上。

运用所学计算机知识来试着解决这个问题是个锻炼和提高我自己编程能力和独立解决问题能力的好机会,可以使我增强信心,为我以后的编程开个好头,故我选择了这个有趣的课题。

1. 2 面对的问题1)解决冲突问题:这个问题包括了行,列,两条对角线;列:规定每一列放一个皇后,不会造成列上的冲突;行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;2)使用数据结构的知识,用递归法解决问题。

八皇后问题-Read

八皇后问题-Read

一.八皇后问题八皇后背景知识国际象棋中皇后威力很大,它可以象“车”一样沿直线上下或左右移动;也可以如同“象”那样沿着斜线移动。

双方的皇后是不能在同一行或同一列或同一斜线上对持的。

那么,在一张空白的国际象棋盘上最多可以放上几个皇后并且不让它们互相攻击呢?这个问题是伟大数学家高斯在十九世纪中期提出来的,并作了部分解答。

高斯在棋盘上放下了八个互不攻击的皇后,他还认为可能有76种不同的放法,这就是有名的“八皇后”问题。

现在我们已经知道八皇后问题有92个解答。

那么你能试着找出几种方法吗?如果你动手试试,就一定会发现开头几颗皇后很容易放置,越到后来就越困难。

由于我们的记忆有限,很可能在某个位置放过子后来证明不行取消了,但是以后又重新放上子去试探,这样就会不断地走弯路,花费大量的精力。

因此,必须找到一个简易有效、有条不紊的法则才行。

1.1分析1.1.1问题描述:八皇后问题是想把八个皇后放在一个棋盘上,并且她们之间不会相互攻击。

按照国家象棋的规则,皇后可以吃掉任何一个和她处在同一行、同一列、或同一斜线(包括两条对角线)上的其他棋子。

如图下所示,皇后所在的行、列及对角线(如图中斜线所示)对其他棋子都是不安全的,而其他地方的棋子则不会受到皇后的威胁。

因此,一个皇后放好以后,它所在的列、行、两条对角线上的地方都不能放其他棋子。

根据这个规则,我们可以利用一个函数来判断某个位置是否安全,安全的位置说明它所在的同一行、同一列或两条线上都没有放置过皇后,因此不会出现皇后互相攻击的情况;否则该位置不安全。

其具体实现过程是找出所有放置的皇后,将他们的位置与该位置进行比较判断。

又注意到同一行只能放一个皇后,因此,只需要对前面的各行逐行扫描皇后,就可以找出所有皇后的位置。

下图是其中一种摆放皇后的方法:1.1.2基本要求:编写实现八皇后问题的非递归解法,输出八皇后问题的中所有摆放皇后的方法,使它可以满足条件。

1.2课程设计目的:深入理解数据结构的基本理论,掌握数据存储结构的设计方法,掌握基于数据结构的各种操作的实现方法,训练对基础知识和基本方法的综合运用能力,增强对算法的理解能力,提高软件设计能力。

八皇后问题的解决方案

八皇后问题的解决方案

算法总结
3
解决八皇后问题常用算法
3.1
枚举法解决八皇后问题
3.2
非递归回溯法解决八皇后问题
3.3
递归回溯法解决八皇后问题
3.0
八皇后问题约束条件
a( i ) 1 2 3 4 5 6 7 8 a( 1) 2 0 -1 3 -2 4 -3 5 -4 6 -5 7 -6 8 -7 9
a( 2 ) a( 3 ) a( 4) a( 5 ) a( 6) a( 7 ) a( 8)
9 3 10 2 11 1 12 0 13 -1 14 -2
9 5 10 4 11 3 12 2 13 1 14 0 15 -1
9 7 10 6 11 5 12 4 13 3 14 2 15 1 16 0
3.0
八皇后问题约束条件
a( i ) =j 第i行j列放置皇后
判断不同列 a(i)≠a(j) 判断不同对角线 i-a(i)≠j-a(j) 判断不同反对角线 i+a(i)≠j+a(j)
取下一个………………
取下一个q (1)
用语言编程
For q1 = 1 To 8 For q2 = 1 To 8 For q3 = 1 To 8 For q4 = 1 To 8 For q5 = 1 To 8 For q6 = 1 To 8 For q7 = 1 To 8 For q8 = 1 To 8 q(q1) = q1 : q(q2) = q2 : q(q3) = q3 : q(q4) = q4 q(q5) = q5 : q(q6) = q6 : q(q7) = q7 : q(q8) = q8 If putdown(q)=1 Then printstr(q) Next q8 Next q7 Next q6 Next q5 Next q4 Next q3 Next q2 Next q1

8皇后问题分析与解法

8皇后问题分析与解法

递归算法——八皇后问题1、背景问题描述八皇后问题是一个古老而著名的问题,该问题的目标是在8×8的国际象棋棋盘上放置八个皇后,使得任意两个皇后都不在同一行,或同一列或同一对角线上。

如图1所示就是八皇后问题的一个解。

图1 八皇后问题的一个解1854年在柏林的象棋杂志上不同的作者发表了40种不同的解。

大数学家高斯认为有76种不同的方案。

后来有人用图论的方法算出92种不同的解。

能否利用程序算出所有满足条件的解的数目呢?2、抽象表示及存储对于这种矩形排列的棋盘而言,用二维数组存储棋盘的状况是最容易想到的方法。

可以设置一个8*8的二维数组,令有棋子的位置为1,无棋子的部分为0。

事实上,由于8个皇后中任意两个皇后都不在同一行,因此8个皇后只能各自占据一行。

不妨认为8个皇后编号为0、1、……、7,它们各自占据棋盘的第1行、第2行、……、第8行。

从而可以使用长度为8一维数组表示棋盘状态,数组元素的下标表示棋子所在行,数组元素的值表示各个棋子所在的列。

使用的存储方式不同,其采用的算法已有很大区别。

3、问题分析及算法设计假定用二维数组A存储棋盘的情况,可以考虑下面两种思路。

思路一:不考虑任何限制的穷举法。

用8×8的二维数组存储棋盘,若在(i,j)处有子,则令A[i][j]=1,否则A[i][j]=0。

于是8个棋子第1个有64种摆放方法,第2个有63种放法,……,第8个有57种放法,则所有摆放方法有64×63×62×…×57种。

可以列举每一种摆法,而后考察每种方法是否符合条件。

这个计算量非常大。

思路二:考虑经过优化的穷举法(二维数组方案)。

若8个棋子位于8行8列的棋盘中,要求任意两个不同行、不同列,则任一解必然是各行、各列只包含一个棋子,其它情况必然不是解。

于是可以做个8重循环,把每个皇后安排在每行的每个位置都试一遍。

算法如下:将整个棋盘数组赋值为0;for(1号皇后从1行1列到1行8列){将1号皇后能控制的线路(横向、竖线、斜线)全部设为1;for(2号皇后从2行1列到2行8列){if(2号皇后控制的线路全部为0){将2号皇后能控制的线路(横向、竖线、斜线)全部设为2;for(3号皇后从3行1列到3行8列){if(3号皇后控制的线路全部为0){将3号皇后能控制的线路全部设为3;……for(8号皇后从8行1列到8行8列){if(8号皇后控制的线路全部为0){将8号皇后能控制的线路全部设为8;记录该棋盘为一个解;}将8号皇后控制的线路全部恢复为0;}……}将3号皇后控制的线路全部恢复为0;}}将2号皇后控制的线路全部恢复为0;}将1号皇后控制的线路全部恢复为0}上述算法中的多重循环虽易于理解,但程序嵌套结构较为复杂,形式死板,不易扩展。

皇后问题详细的解法

皇后问题详细的解法

for(a[7]=1;a[7]<=8;a[7]++} )
for(a[8]=1;a[8]<=8;a[8]++){
if (check(a,8)=0) continue;
else
for(i=1;i<=8;i++)print(a[i]);
}
10
}
1 回溯法
有“通用的解题法”之称。 回溯法的基本做法是搜索,或是一种组织得井井有条
枚举得有个顺序,否则 轻则有漏的、重复的; 重则无法循环表示。
6
1.按什么顺序去查找所有的解 a.盲目的枚举算法
void main() {
int x[100]; for (x[1]=1;x[1]<=10;x[1]++) for (x[2]=1;x[2]<=10;x[2]++)
for (x[3]=1;x[3]<=10;x[3]++) for (x[4]=1;x[4]<=10;x[4]++) for (x[5]=1;x[5]<=10;x[5]++) for (x[6]=1;x[6]<=10;x[6]++) for (x[7]=1;x[7]<=10;x[7]++) for (x[8]=1;x[8]<=10;x[8]++) if (check(x)==0) { printf(x); }
}
该如何解决冲突的问题呢?
1.行;我们是按照行枚举的,保证了一行一个皇后; 2.列:判断是否存在x[i]=x[j] 3.对角线:主对角线的i-j与从对角线的i+j存在特殊关系,如 图:

八皇后问题(N皇后问题)

八皇后问题(N皇后问题)

⼋皇后问题(N皇后问题)⼋皇后问题,是⼀个古⽼⽽著名的问题,是回溯算法的典型案例。

该问题是国际西洋棋棋⼿马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放⼋个皇后,使其不能互相攻击,即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上,问有多少种摆法。

⾸先来看看这张模拟⼋皇后的图。

这张图说明皇后具有横轴、竖轴以及两个斜轴⽅向的杀伤⼒,也就是像⽶字形⼀样;为了减少判断,我们按照⼀个⽅向往另⼀个⽅向排列,中间不能跳⾏,这样我们就可以只判断已经有皇后的位置,还没有皇后的就可以偷懒不⽤判断了。

我的⽅案是:1.从最下⾯开始排列,然后往上添加,从左往右排列,这样就只需要判断⽐⾃⼰Y坐标低的具有杀伤能⼒的位置有没有皇后就OK ⽅法是把⾃⼰假定要放置皇后的位置的X和Y轴都依据判断特性进⾏处理;例如,左斜线X和Y轴都减1;中间的只需要把Y 轴减1;右边的和左边的相反,X轴加1,Y轴减1;注意处理边界问题。

2.为了找到合适的位置我们需要在查找失败的时候具备回溯的能⼒,就需要退回到前⼀⾏(Y=Y-1,注意XY是否到边界),直⾄能回溯或者全部判断完毕,每次回溯的时候记得X轴要从头开始 3.通过⼀个数据结构记录正在查找的⽅案,通过另⼀个数据结构记录已经找到的⽅案,当然也可以⽤⼀个变量记录⽅案个数下⾯这张⿊⾊背景是其中⼀个⽅案的截图,第⼀⾏代表皇后的坐标xy;后⾯的是棋盘,这⾥输出竖轴是x,横轴是y,从上到下,从左到右,其中*是边界,空格是空区,#是皇后。

#include <iostream>#include <cstring>#include "DTString.h"#include "LinkList.h" // 这⾥使⽤链表存储皇后的位置using namespace std;using namespace DTLib;template <int SIZE> // N皇后问题,SIZE表⽰皇后个数或者棋盘⼤⼩class QueenSolution : public Object{protected:enum { N = SIZE + 2 }; // N表⽰棋盘⼤⼩,为了边界识别,棋盘四周都要加⼀格struct Pos : public Object // ⽅位结构体{Pos(int px = 0, int py = 0) : x(px), y(py) { }int x;int y;};int m_chessboard[N][N]; // 棋盘,0表⽰空位,1表⽰皇后,2表⽰边界Pos m_direction[3]; // 共3个⽅向;⽅向-1、-1表⽰左斜线;0、-1表⽰下⽅;1、-1表⽰右斜线;⾸先从最下⽅开始,所以只需考虑下⾯的⾏。

8 经典八皇后问题(回溯法)(蓝桥杯)

8 经典八皇后问题(回溯法)(蓝桥杯)

1.引子中国有一句古话,叫做“不撞南墙不回头",生动的说明了一个人的固执,有点贬义,但是在软件编程中,这种思路确是一种解决问题最简单的算法,它通过一种类似于蛮干的思路,一步一步地往前走,每走一步都更靠近目标结果一些,直到遇到障碍物,我们才考虑往回走。

然后再继续尝试向前。

通过这样的波浪式前进方法,最终达到目的地。

当然整个过程需要很多往返,这样的前进方式,效率比较低下。

2.适用范围适用于那些不存在简明的数学模型以阐明问题的本质,或者存在数学模型,但是难于实现的问题。

3.应用场景在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突。

国际象棋的棋盘如下图所示:1.2.3.package algorithm ;4.public class Empress {5.6.private int n ; //皇后个数7.private int[] x ; //当前解8.private long sum ; //当前已找到的可行方案数9.private static int h ; //记录遍历方案序数10.11. public Empress(){12. this.sum = 0 ; //初始化方案数为1,当回溯到最佳方案的时候,就自增113. this.n = 8 ; //求n皇后问题,由自己定义14. this.x = new int[n+1]; //x[i]表示皇后i放在棋盘的第i行的第x[i]列15. h = 1 ; //这个是我额外定义的变量,用于遍历方案的个数,请看backTrace()中h变量的作用,这里将它定义为static 静态变量16. }17.18. public boolean place (int k){19. for (int j = 1 ; j < k ; j++){20. //这个主要是刷选符合皇后条件的解,因为皇后可以攻击与之同一行同一列的或同一斜线上的棋子21. if ( (Math.abs(k - j)) == (Math.abs(x[j]-x[k])) || (x[j] == x[k]) ){22. return false ; //如果是与之同一行同一列的或同一斜线上的棋子,返回false;23. }24. }25. return true ;//如果不是与之同一行同一列的或同一斜线上的棋子,返回true;26. }27.28. public void backTrace (int t){29. if (t > n){ //当t>n时,算法搜索到叶节点,得到一个新的n皇后互不攻击放置方案,方案数加130. sum ++ ; //方案数自增131. System.out.println ("方案" + (h++) + "");32. print(x);33. System.out.print ("/n----------------/n");//华丽的分割线34. }else { //当t<=n时,当前扩展的结点Z是解空间中的内部结点,该节点有x[i]=1,2,…,n共n个子结点,35. //对于当前扩展结点Z的每一个儿子结点,由place()方法检测其可行性,36. //并以深度优先的方式递归地对可行子树搜索,或剪去不可行子数37. for (int i = 1 ; i <= n ; i++){38. x[t] = i ;39. if (place (t)){ //检查结点是否符合条件40. backTrace (t+1);//递归调用41. }42. }43. }44. }45.46. public void print (int[] a){ //打印数组,没啥的47. for (int i = 1 ; i < a.length ; i++){48. System.out.print ("皇后" + i + "在" + i + "行" +a[i] + "列、");49. }50. }51.52. public static void main (String[] args){53. Empress em = new Empress();54. em.backTrace(1); //从1开始回溯55. System.out.println ("/n详细方案如上所示,"+"可行个数为:" + em.sum);56. }57.}/*output:八皇后问题只有92种方案,这里只给出其中的三个方案58.方案159.皇后1在1行1列、皇后2在2行5列、皇后3在3行8列、皇后4在4行6列、皇后5在5行3列、皇后6在6行7列、皇后7在7行2列、皇后8在8行4列、60.----------------61.方案262.皇后1在1行1列、皇后2在2行6列、皇后3在3行8列、皇后4在4行3列、皇后5在5行7列、皇后6在6行4列、皇后7在7行2列、皇后8在8行5列、63.----------------64. .65. .66. .67.方案9268.皇后1在1行8列、皇后2在2行4列、皇后3在3行1列、皇后4在4行3列、皇后5在5行6列、皇后6在6行2列、皇后7在7行7列、皇后8在8行5列、69.----------------70.*///~。

八皇后问题最简单算法

八皇后问题最简单算法

八皇后问题最简单算法
八皇后问题最简单算法是使用回溯法。

1. 回溯法在求解八皇后问题时,会生成一个8位的二进制数,每一位代表一列是否放置皇后。

如果某一列放置了皇后,则该位为1,否则为0。

2. 在放置皇后时,如果当前位置可以放置皇后,则尝试放置。

如果放置后当前位置形成了一个合法的棋盘,则继续递归地放置下一个皇后。

如果放置后形成了一个不合法的棋盘,则回溯到上一个状态,尝试其他位置。

3. 如果所有8个皇后都放置完毕,且形成了一个合法的棋盘,则找到了一个解。

以上信息仅供参考,如需了解更多信息,建议查阅八皇后问题相关书籍或咨询专业人士。

八皇后问题的最佳解决方案 123

八皇后问题的最佳解决方案 123

八皇后问题的最佳解决方案(陕西师范大学计算机科学学院10级计科一班,西安,710062)摘要:回溯法实际是一个类似枚举的搜索尝试方法,它的主题思想是在搜索尝试中找问题的解,当不满足求解条件就”回溯”(返回),尝试别的路径。

回溯算法是尝试搜索算法中最为基本的一种算法,其采用了一种“走不通就掉头”的思想,作为其控制结构。

本文主要描述递归回溯与非递归回溯,并用这两个算法解决经典的“八皇后”问题,找出该问题的最佳解决方案。

关键词:回溯法;递归;非递归;深度优先搜索;约束条件;枚举Eight queen problem the best solutionZhao Ya-wen ,Zhao-Shanshan ,Zhong mei ,Duan Xi-juan(School of Computer Science ,Shanxi Normal University ,Xi’an ,710062)Abstract:Backtracking is actually a similar enumerated search try method ,It is the theme in the search to findthe solution of problems.,When not solving condition is "back" (return), Try the other path. Backtracking algorithm is trying to search algorithm is the most basic an algorithm, The use of a "walk impassability will turn" thought, As its control structure. This paper mainly describe recursive back and the recursive back, And the two algorithms to solve the classic "eight queen", To find the best solution to the problem.Keywords:Backtracking; Recursive; The recursive; Depth first search; Constraint conditions; enumeration.1引言在用回溯算法解决问题中每向前走一步都有很多路需要选择,但当没有决策的信息或决策的信息不充分时,只好尝试某一路线向下走,到一定程度后得知此路不通时,再回溯到上一步尝试其他路线;当然再尝试成功时,则问题得解算法结束。

八皇后所有可能的方案

八皇后所有可能的方案
▕ █ ★ █ █▏
▔▔▔▔▔▔▔▔
第 7种方案(★表示皇后)
▁▁▁▁▁▁▁▁
▕█★█ █ █ ▏
▕ █ █★█ █▏
▕█ █ █ ★ ▏
▕ █ ★ █ █▏
▕★ █ █ █ ▏
▕ █ █ █ ★▏
▕█ █ █★█ ▏
▕ █ █ ★ █▏
▔▔▔▔▔▔▔▔
第14种方案(★表示皇后)
▁▁▁▁▁▁▁▁
▕█ ★ █ █ ▏
▕ █ █★█ █▏
▕█★█ █ █ ▏
▕ █ █ █ ★▏
▕★ █ █ █ ▏
▕ █ █ █★█▏
▕█ █★█ █ ▏
▕ █ █★█ █▏
▔▔▔▔▔▔▔▔
第33种方案(★表示皇后)
▁▁▁▁▁▁▁▁
▕█ █★█ █ ▏
▕ ★ █ █ █▏
▕█ █ █ ★ ▏
▕ █★█ █ █▏
▕█ █ █★█ ▏
▕ █ █ █ ★▏
▕ █ █★█ █▏
▔▔▔▔▔▔▔▔
第20种方案(★表示皇后)
▁▁▁▁▁▁▁▁
▕█ ★ █ █ ▏
▕ █ █ ★ █▏
▕█★█ █ █ ▏
▕ █ █ █★█▏
▕█ █ ★ █ ▏
▕★█ █ █ █▏
▕█ █ █ █★▏
▕ █ █ ★ █▏
▔▔▔▔▔▔▔▔
第27种方案(★表示皇后)
▁▁▁▁▁▁▁▁
▕█ ★ █ █ ▏
▕ █ █ █★█▏
▕█★█ █ █ ▏
▕ █ █ █ ★▏
▕█ █ █★█ ▏
▕ █ ★ █ █▏

八皇后问题(递归+非递归)

八皇后问题(递归+非递归)

八皇后问题(递归+非递归)Xredman posted @ 2009年6月04日 21:15 in 以前博文 , 442 阅读一.问题描述在8×8格的国际象棋棋盘上放置八个皇后,使得任意两个皇后不能互相攻击,即任何行、列或对角线(与水平轴夹角为45°或135°的斜线)上不得有两个或两个以上的皇后。

这样的一个格局称为问题的一个解。

请用递归与非递归两种方法写出求出八皇后问题的算法。

二.解题思路描述一个正确的解应当是每一列,每一行,每一条斜线上均只有一个皇后。

对于递归算法,本人才有模拟的方式进行,而且,我觉得开辟一个二维数组更显而易见。

首先,从空棋盘开始摆放,保证第m行m个皇后互不攻击,然后摆放第m+1个皇后。

当然对于第m+1个皇后可能有多种摆放方法,由此,我必须一一枚举,采用回溯策略是可行且合乎逻辑的。

而对于非递归算法,我只是借助于书本上一个递归改为非递归的框架,依次搭建而已。

在此过程中,我采用一维数组,一位对于八皇后问题,每一行不可能存在二个及二个以上的皇后,board[i]表示第i行棋盘摆放的位置为第board[i]列。

递归方法借助于系统提供的栈,而我非递归算法的实现,仅仅是自己构造一个栈而已。

递归解法#include <iostream>#include <cstdio>#include <sys/timeb.h>using namespace std;const int MAX_SIZE = 100;enum flag {blank ='X',queen = 1};char Chess[MAX_SIZE][MAX_SIZE];//棋盘图int n;//解决n皇后问题int total;//用于计摆放方式void Init(){//对棋牌进行初始化for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)Chess[i][j] = blank;total = 0;//初始时有零中摆放方式}bool Judge(int r,int c){//判断(r,c)位置是否可放置int i,j;for(i = r + 1; i < n; i++)if(Chess[i][c] == queen)return false;//说明c列上已有一皇后for(i = c + 1; i < n; i++)if(Chess[r][i] == queen)return false;//说明r行上已有一皇后for(i = r + 1, j = c + 1; (i < n) && (j < n); i++, j++)if(Chess[i][j] == queen)return false;//45度斜线上已有一皇后for(i = r + 1, j = c - 1; (i <n) && (j >= 0); i++, j--)if(Chess[i][j] == queen)return false;//135度斜线上已有一皇后return true;//排除四种情况后,说明(r,c)点可放置皇后}void Backtrack(int k,int cnt){//回溯算法主程序if(k < 0 || cnt == n)//棋牌摆放完毕 or 以摆满n后{if(cnt == n){printf("No.%d:\n",++total);for(int i = 0; i < n; i++){for(int j = 0; j < n; j++)printf(" %c ",Chess[i][j]);putchar('\n');}putchar('\n');}}else{int r = k / n, c = k % n;if(Judge(r,c)){//可放置一皇后Chess[r][c] = queen;Backtrack(k-1,cnt+1);Chess[r][c] = blank;}Backtrack(k-1,cnt);}}int main(){//此为主函数timeb t1,t2;long kk;cout<<"输入皇后个数:";while(cin>>n){Init();ftime(&t1);Backtrack(n*n-1,0);ftime(&t2);cout<<"计算"<<n<<"后问题总共可有"<<total<<"种摆法!"<<endl;kk = (t2.time-t1.time)*1000 +litm;cout<<"本次回溯耗时:"<<kk<<"毫秒"<<endl;system("PAUSE");cout<<"输入皇后个数:";}return0;}非递归解法#include <iostream>#include <sys/timeb.h>#define N 100using namespace std;int board[N];int n,sum;void init(){for(int i = 1; i <= n; i++)board[i] = 0;}void display(){int i,j;cout<<"No."<<sum<<endl;for(i = 1; i <= n; i++){for(j = 1; j <= n; j++)if(board[i] == j)cout<<"Q ";elsecout<<"X ";cout<<endl;}cout<<endl;}bool canPut(int k){for(int i = 1; i < k; i++)if((abs(k - i) == abs(board[k] - board[i])) || board[i] == board[k])return false;//1.是否在同一斜线;2.是否位于同一列return true;}void Backtrack(){board[1] = 0;int k = 1;while(k > 0){board[k]++;while((board[k] <= n) && !(canPut(k)))board[k] += 1;if(board[k] <= n)if(k == n){sum++;display();}else{k++;board[k] = 0;}elsek--;}}int main(){timeb t1,t2;long kk;cout<<"输入皇后个数:";while(cin>>n){init();sum = 0;ftime(&t1);Backtrack();ftime(&t2);cout<<"总共排列方式为:"<<sum<<endl;kk = (t2.time-t1.time)*1000 + litm; cout<<"本次回溯耗时:"<<kk<<"毫秒"<<endl;system("PAUSE");cout<<"输入皇后个数:";}return0;}。

八皇后问题详细的解法

八皇后问题详细的解法
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
}
}
23
20
2 回溯法应用-算法框架-递归算法框架
int a[n]; Queens(int k) { if (k>n) 即表示最后一个皇后摆放完毕,输出结果;
else for(i=下界 ; i<=上界; i++) //枚举K个皇后所有可能的路径 {依次从列顶端开始搜索,一直到列底端,直到找到合适位置,如
果未找到,自动返回上层递归
的,能避免不必要搜索的穷举式搜索法。这种方法适 用于解一些组合数相当大的问题。 回溯法在问题的解空间树中,按深度优先策略,从根 结点出发搜索解空间树。算法搜索至解空间树的任意 一点时,先判断该结点是否包含问题的解。如果肯定 不包含,则跳过对该结点为根的子树的搜索,逐层向 其祖先结点回溯;否则,进入该子树,继续按深度优 先策略搜索。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i++) 它只能解决八皇后问
print(a[i]); }
题,而不能解决任意
}}}}}}}

八皇后问题详细的解法

八皇后问题详细的解法
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
2021/5/27
3
八皇后问题
要在8*8的国际象棋棋盘中放8个皇后,使任意两个皇 后都不能互相吃掉。规则:皇后能吃掉同一行、同一 列、同一对角线的任意棋子。求所有的解。
八皇后的两组解
18
2 回溯法应用-算法说明
八皇后问题中的核心代码: 遍历过程函数; check函数。
解决此类问题的核心内容: 解空间树的搜索算法; 估值/判断函数:判断哪些状态适合继续扩展,或者作 为答案状态。
2021/5/27
19
2 回溯法应用-n皇后问题
介绍过的方法: c递归回溯算法; d非递归回溯算法;
}
2021/5/27
7
该如何解决冲突的问题呢?
1.行;我们是按照行枚举的,保证了一行一个皇后; 2.列:判断是否存在x[i]=x[j] 3.对角线:主对角线的i-j与从对角线的i+j存在特殊关系,如 图:
2021/5/27
8
盲目的枚举算法
约束条件? 不在同一列:xi≠xj; 不在同一主对角线上:xi-i ≠ xj-j; 不在同一负对角线上:xi+i ≠ xj+j。
八皇后问题
2021/5/27
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2021/5/27
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
果未找到,自动返回上层递归
a[k]=i; if (check(a,k)) //满足限界函数和约束条件,不冲突 //递归摆放下一个皇后Queens (k+ 1);} } }

(2023)八皇后问题实验报告(一)

(2023)八皇后问题实验报告(一)

(2023)八皇后问题实验报告(一)实验背景八皇后问题,是一道经典的数学问题,简要地说:在一个 8x8 的国际象棋棋盘上摆放 8 个皇后,使其不能互相攻击。

即任意两个皇后都不能处于同一行、同一列或同一斜线上。

实验目的1.理解并掌握八皇后问题的基础算法;2.利用Python编写程序,解决八皇后问题;3.掌握递归算法与回溯算法的基本思想;4.分析算法时间复杂度,理解优化算法的重要性。

实验步骤1.利用递归算法,枚举每一行中皇后的位置;2.每一行都有8个候选位置,依次尝试每个位置是否可行;3.如果某个位置可行,继续对下一行进行递归;4.如果都不可行,则回溯到上一行,重新选择位置;5.直到第8行所有位置都选择完成,输出结果。

程序实现及结果def conflict(pos, i):for j in range(i):if abs(pos[i] - pos[j]) in (0, i - j):return Truereturn Falsedef queen(num =8, pos = ()):for i in range(num):if not conflict(pos, i):if len(pos) == num -1:yield (i, )else:for result in queen(num, pos + (i, )):yield (i, ) + resultfor solution in list(queen(8)):print(solution)程序输出结果为所有可能的八皇后问题解决方案,共计92种:(0, 4, 7, 5, 2, 6, 1, 3)(0, 5, 7, 2, 6, 3, 1, 4)…(7, 3, 0, 2, 5, 1, 6, 4)(7, 4, 2, 0, 6, 1, 3, 5)结论与分析1.通过本实验,我们深入地理解了递归算法与回溯算法的基本思想,并将其应用到八皇后问题的解决中;2.程序的输出结果表明:八皇后问题有92种可能的解决方案;3.根据算法的时间复杂度分析,当八皇后问题的规模更大时,应该采用更高效的算法进行优化;4.进一步研究表明,通过基因算法等优化算法可以提高八皇后问题的解决效率。

第一讲:八皇后问题

第一讲:八皇后问题

//验证检查左上至右下某斜行是否至多有一个true public static boolean isLeftUpToRightDownOK(boolean[][] data,int i) { int count =0; for(int k=0;k<8;k++) { if (k+i<0 || k+i>=8) continue ; if (data[k][k+i]) count++ ; } return count<=1; }
代码框架
public static void solution() { Stack<ChessBoard> stack = new Stack<ChessBoard>(); stack.push( new ChessBoard() ); //空棋盘进栈 while(!stack.empty()) { ChessBoard board = stack.pop(); //取栈顶元素 if ( board 可被继续放置皇后 ) { int row = board 可在哪一行被继续放置皇后 int[] columns = board 可在该行哪几列放皇后 for(int j=0;j<columns.length;j++) { ChessBoard newBoard = 复制产生新的ChessBoard ; //放置皇后,存入堆栈 newBoard.place(row, columns[j]) ; stack.push(newBoard); } } else if (board.isAnswer()) { //栈顶元素是求解的答案,输出 board.printResult(); } } }

dfs解决八皇后问题以及其他图搜索问题

dfs解决八皇后问题以及其他图搜索问题

dfs解决⼋皇后问题以及其他图搜索问题33. N皇后问题中⽂Englishn皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同⼀⾏,同⼀列,同⼀斜线)。

给定⼀个整数n,返回所有不同的n皇后问题的解决⽅案。

每个解决⽅案包含⼀个明确的n皇后放置布局,其中“Q”和“.”分别表⽰⼀个⼥王和⼀个空位置。

样例例1:输⼊:1输出:[["Q"]]例2:输⼊:4输出:[// Solution 1[".Q..","...Q","Q...","..Q."],// Solution 2["..Q.","Q...","...Q",".Q.."]]挑战你能否不使⽤递归完成?class Solution:"""@param: n: The number of queens@return: All distinct solutions"""def solveNQueens(self, n):# write your code hereself.result = []self.position = [-1]*nself.dfs(n, start_index=0)return self.resultdef to_chars(self, position):ans = []n = len(position)for i in range(0, n):row = ['.']*nrow[position[i]] = 'Q'ans.append("".join(row))return ansdef is_valid_pos(self, position, start_index, k):for i in range(start_index):if position[i] >= 0 and (position[i] == k or \abs(start_index-i) == abs(k-position[i])):return Falsereturn Truedef dfs(self, n, start_index):if start_index == n:self.result.append(self.to_chars(self.position))returnfor i in range(0, n):if start_index < n and self.is_valid_pos(self.position, start_index, i):self.position[start_index] = iself.dfs(n, start_index+1)self.position[start_index] = -1这种题⽬写起来真的是⽐较繁琐。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

淮阴工学院数据结构课程设计报告设计题目:八皇后系(院):计算机工程系专业:信息安全班级:信息 1 0 6 学生姓名: 叶青学号:1061303127指导教师:张亚红寇海洲胡荣林夏森学年学期: 2007 ~ 2008 学年第 2 学期2008 年 6 月25 日设计任务书摘要:八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。

而本课程设计本人的目的也是通过用c++语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.使用递归方法最终将其问题变得一目了然,更加易懂。

关键词:八皇后; c++; 递归法目录1. 课题综述 (1)1.1课题的来源及意义 (1)1.2面对的问题 (1)2. 需求分析 (1)2.1涉及到的知识 (1)2.2软硬件的需求 (1)2.3功能需求 (2)3. 概要设计 (2)4. 详细设计和实现 (2)4.1算法描述及详细流程图 (2)4.1.1算法描述 (3)4.1.2算法流程图 (3)5. 代码编写及详细注释 (4)6. 程序调试 (7)6.1调试过程、步骤及遇到的问题 (7)7. 运行与测试 (7)7.1运行演示 (7)总结 (9)致谢 (10)参考文献 (11).1. 课题综述1. 1课题的来源及意义八皇后问题是一个古老而著名的问题,该问题是十九世纪著名的数学家高斯1850年提出的。

在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。

所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。

到了现代,随着计算机技术的飞速发展,这一古老而有趣的数学游戏问题也自然而然的被搬到了计算机上。

运用所学计算机知识来试着解决这个问题是个锻炼和提高我自己编程能力和独立解决问题能力的好机会,可以使我增强信心,为我以后的编程开个好头,故我选择了这个有趣的课题。

1. 2 面对的问题1)解决冲突问题:这个问题包括了行,列,两条对角线;列:规定每一列放一个皇后,不会造成列上的冲突;行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;2)使用数据结构的知识,用递归法解决问题。

2. 需求分析2. 1 涉及到的知识本次课程设计中,用到的主要知识有:递归法的运用,for语句的灵活运用,数据结构中树知识的灵活运用、栈及数组的掌握。

2. 2 软硬件的需求1)系统要求:win98以上操作系统;2) 语言平台:tc++或vc++6.0;2. 3 功能需求当运行程序时,在屏幕上显示每一种方法八个皇后的相对位置,要用比较直观的界面显示。

3. 概要设计本课件学生是用循环递归循环来实现的,分别一一测试了每一种摆法,并把它拥有的92种变化表现出来。

在这个程序中,我的主要思路以及思想是这样的: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](从对角线),根据程序的运行,去决定主从对角线是否放入皇后;4. 详细设计和实现4. 1 算法描述及详细流程图4.1.1 算法描述A、数据初始化。

B、从n列开始摆放第n个皇后(因为这样便可以符合每一竖列一个皇后的要求),先测试当前位置(n,m)是否等于0(未被占领)。

如果是,摆放第n个皇后,并宣布占领(记得姚横列竖列斜列一起设置),接着进行递归;如果不是,测试下一个位置(n,m+1),但是如果当n<=8,m=8时,发现此时已无法摆放时,便要进行回溯。

从问题的某一种可能出发,搜索从这种情况能出发,继续搜索,这种不断“回溯”的寻找解的方法,称为“回溯法”。

C、使用数组实现回溯法的思想。

D、当n>8时,便打印出结果。

E、输出函数我使用printf输出,运行形式为:第m种方法为:* * * * * * * *4.1.2 算法流程图5. 代码编写及详细注释#include <conio.h>#include <math.h>#include <stdlib.h>#include <stdio.h>#include <iostream.h>#define QUEENS 8int 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) //!参数n从0开始,等于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个皇后的位置依次于前面n-1个皇后的位置比较。

{ 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");}6. 程序调试6. 1调试过程、步骤及遇到的问题在完整程序调试时遇到几个小问题,后经细心改正后才把调试工作做完。

例如:当用printf输出时,出现了一些错误,几经调试后,发现原来是缺少了stdio.h 这样一个头文件,添加了头文件后, 还出现了一些问题,逻辑错误导致程序死循环或不循环或循环一小部分,但是编译时却没有错误,就是没有正确的输出答案,一开始我也不知道是怎么回事,通过和同学的交流,发现是逻辑错误,经过改正后,程序终于可以运行了.7. 运行与测试7.1运行演示总结通过了19周这个星期的程序设计,我从中得到了许多的经验以及软件设计的一些新的思路;从这个八皇后问题设计以及分析中,本人从中理解到了数据结构对于计算机软件设计的重要性,它的使用,可以改变一个软件的运行周期,也可以将软件的思路从繁化简,并且都能够通过数据结构的相关引导,将本身以前编程思想进行扩充,发展;这也是在这次课程设计中我所掌握得到的。

但由于我的基本知识还不是那么扎实,也缺乏对软件设计的经验,在这过程中也出现了一些问题,如,八皇后在变成初期由于没真正体会到数据结构中“树”在里面的运用,将程序往大一时c语言的方向发展,不自觉的采用了非递归的算法,结果大大增加了程序的复杂程度。

并且也让整个程序的时间复杂度变得更大;在后来学生对数据结构的第六章进行了比较深入的研读,才发现了数据结构树的实际运用的空间是相当的大,并且,通过了重温树的回溯,以及二叉树的遍历,最终将程序进行了一次较大的改造。

并且通过思考,再将以前的数组知识加以运用才最终解决了这个问题,整个程序的算法的可看性也有了相当的改进。

课程设计随着时间的推移,也即将结束了,但这个学期数据结构的学习还是具有相当大的意义,它从一个程度上改变了我们的编程思想,如何将一个程序快速而又准备的进行编写,进行编译,都成为了我们思考的重点,也通过这一个学期的学习,我们将数据结构的思想带入到了我们以后的编程学习中去。

在这个阶段,我也明白了,好的思想,不能提留于字面上的认知,还需要的是平时多练多写一些相关的程序,并且通过修改,加入新的算法去尝试改变自己的一些编程思想。

保持更新算法的速度,这才是关键。

相关文档
最新文档