八皇后问题
八皇后解题思路

1.引子中国有一句古话,叫做“不撞南墙不回头",生动的说明了一个人的固执,有点贬义,但是在软件编程中,这种思路确是一种解决问题最简单的算法,它通过一种类似于蛮干的思路,一步一步地往前走,每走一步都更靠近目标结果一些,直到遇到障碍物,我们才考虑往回走。
然后再继续尝试向前。
通过这样的波浪式前进方法,最终达到目的地。
当然整个过程需要很多往返,这样的前进方式,效率比较低下。
2.适用范围适用于那些不存在简明的数学模型以阐明问题的本质,或者存在数学模型,但是难于实现的问题。
3.应用场景在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突。
国际象棋的棋盘如下图所示:4.分析基本思路如上面分析一致,我们采用逐步试探的方式,先从一个方向往前走,能进则进,不能进则退,尝试另外的路径。
首先我们来分析一下国际象棋的规则,这些规则能够限制我们的前进,也就是我们前进途中的障碍物。
一个皇后q(x,y)能被满足以下条件的皇后q(row,col)吃掉1)x=row(在纵向不能有两个皇后)2) y=col(横向)3)col + row = y+x;(斜向正方向)4) col - row = y-x;(斜向反方向)遇到上述问题之一的时候,说明我们已经遇到了障碍,不能继续向前了。
我们需要退回来,尝试其他路径。
我们将棋盘看作是一个8*8的数组,这样可以使用一种蛮干的思路去解决这个问题,这样我们就是在8*8=64个格子中取出8个的组合,C(64,80) = 4426165368,显然这个数非常大,在蛮干的基础上我们可以增加回溯,从第0列开始,我们逐列进行,从第0行到第7行找到一个不受任何已经现有皇后攻击的位置,而第五列,我们会发现找不到皇后的安全位置了,前面四列的摆放如下:第五列的时候,摆放任何行都会上图所示已经存在的皇后的攻击,这时候我们认为我们撞了南墙了,是回头的时候了,我们后退一列,将原来摆放在第四列的皇后(3,4)拿走,从(3,4)这个位置开始,我们再第四列中寻找下一个安全位置为(7,4),再继续到第五列,发现第五列仍然没有安全位置,回溯到第四列,此时第四列也是一个死胡同了,我们再回溯到第三列,这样前进几步,回退一步,最终直到在第8列上找到一个安全位置(成功)或者第一列已经是死胡同,但是第8列仍然没有找到安全位置为止总结一下,用回溯的方法解决8皇后问题的步骤为:1)从第一列开始,为皇后找到安全位置,然后跳到下一列2)如果在第n列出现死胡同,如果该列为第一列,棋局失败,否则后退到上一列,在进行回溯3)如果在第8列上找到了安全位置,则棋局成功。
回溯算法原理和几个常用的算法实例

回溯算法原理和几个常用的算法实例回溯算法是一种基于深度优先的算法,用于解决在一组可能的解中找到满足特定条件的解的问题。
其核心思想是按照特定的顺序逐步构造解空间,并通过剪枝策略来避免不必要的。
回溯算法的实现通常通过递归函数来进行,每次递归都尝试一种可能的选择,并在达到目标条件或无法继续时进行回溯。
下面介绍几个常用的回溯算法实例:1.八皇后问题:八皇后问题是一个经典的回溯问题,要求在一个8×8的棋盘上放置8个皇后,使得每个皇后都不能相互攻击。
即每行、每列和对角线上都不能有两个皇后。
通过在每一列中逐行选择合适的位置,并进行剪枝,可以找到所有满足条件的解。
2.0-1背包问题:0-1背包问题是一个经典的组合优化问题,要求在一组物品中选择一些物品放入背包,使得其总重量不超过背包容量,同时价值最大化。
该问题可以通过回溯算法进行求解,每次选择放入或不放入当前物品,并根据剩余物品和背包容量进行递归。
3.数独问题:数独问题是一个经典的逻辑推理问题,要求在一个9×9的网格中填入数字1-9,使得每行、每列和每个3×3的子网格中都没有重复数字。
该问题可以通过回溯算法进行求解,每次选择一个空格,并依次尝试1-9的数字,然后递归地进行。
4.字符串的全排列:给定一个字符串,要求输出其所有可能的排列。
例如,对于字符串"abc",其所有可能的排列为"abc"、"acb"、"bac"、"bca"、"cab"和"cba"。
可以通过回溯算法进行求解,每次选择一个字符,并递归地求解剩余字符的全排列。
回溯算法的时间复杂度通常比较高,因为其需要遍历所有可能的解空间。
但是通过合理的剪枝策略,可以减少的次数,提高算法效率。
在实际应用中,可以根据具体问题的特点来设计合适的剪枝策略,从而降低算法的时间复杂度。
人工智能论文-遗传算法实现八皇后问题

南京理工大学人工智能大论文题目:遗传算法实现八皇后问题姓名:xxxx学号:xxxxxxxxxxxxxx专业:xxxxxxxxxx院系:xxxxxxxxxxxxxxxx老师:xxxxxx日期:2015年12月20日目录摘要 (3)一、实验背景 (4)1.1 N皇后问题描述 (4)1.2 遗传算法 (4)二、实验目的 (5)三、实验内容 (5)四、实验步骤 (5)4.1编码方案 (5)4.2初始化种群 (6)4.3适应度的计算 (7)4.4遗传算子 (8)4.4.1选择算子 (8)4.4.2交叉方法 (8)4.4.3变异方法 (8)4.5局部搜索 (10)4.6终止策略 (10)4.7实现描述 (10)五、实验结果和分析 (11)六、总结与思考 (12)摘要众所周知的八皇后问题是一个非常古老的问题,具体描述如下:在8*8的国际象棋棋盘上放置了八个皇后,要求没有一个皇后能吃掉另一个皇后,即任意两个皇后都不处于棋盘的同一行、同一列或同一对角线上。
本实验要求设计并实现解决八皇后问题的遗传算法。
能够给定任意一个初始状态,使用遗传算法搜索最优解,程序能显示优化的计算过程。
独立运行20次以上,统计遗传算法的寻优指标(包括是否找到最优解、平均迭代次数等)。
本次设计旨在学习各种算法,训练对基础知识和基本方法的综合运用及变通能力,增强对算法的理解能力,提高软件设计能力,在实践中培养独立分析问题和解决问题的作风和能力。
通过本实验的设计与编程实现让学生掌握基于状态空间知识表示的局部搜索策略,对遗传算法中的编码方法以及选择、复制、交叉、变异等基本算子有深入的理解,熟练运用C++,编写一个遗传算法解决八皇后问题的应用程序。
关键词:八皇后;遗传算法;C++一、实验背景1.1 N皇后问题描述N皇后问题描述如下:在n n格棋盘上放置彼此不受攻击的N个皇后。
按国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
N皇后问题等价于在以下三个约束条件:任何2个皇后不放在同一行;任何2个皇后不放在同一列;任何2个皇后不放在同斜线。
八皇后问题作品报告

八皇后问题作品报告八皇后问题:国际象棋中,皇后可以在横、竖、斜线上不限步数地吃掉其他棋子,如何将8个皇后放在8×8的棋盘上,使得它们不能互相攻击源代码://八皇后问题源代码#include ""#define N 9int locate[N]={0};//0号单元不用,locate[m]=n表示第m行第n列中放入皇后int num=0;//用来标记八皇后的解法种类void Trial(int i,int n){int m,p,q;if (i>n){for(m=1;m<N;m++){printf("(%d,%d) ",m,locate[m]);}num++;printf("\n");}else{for(p=1;p<N;p++){for(q=1;q<i;q++){//用行进行的选择,排除同一列,同一对角线上的情况if (p==locate[q]||p==locate[q]+(i-q)||p==locate[q]-(i-q)){break;}}if (q==i){locate[i]=p;Trial(i+1,N-1);}}}}void main(){int j;for(j=1;j<N;j++){locate[1]=j;Trial(2,N-1);}printf("八皇后问题的答案总数num=%d\n",num);}使用方法:上述程序采用了递归调用和近似于枚举的方法。
本程序采用一行一行进行搜索,排除同一列(p==locate[q]),同一对角线上(p==locate[q]+(i-q)||p==locate[q]-(i-q))的位置,然后进行递归。
结果展示:。
八皇后问题

计算机科学与技术专业数据结构课程设计报告设计题目:八皇后问题目录1需求分析 (2)1.1功能分析 (2)1.2设计平台 (3)2概要设计 (3)2.1算法描述 (4)2.2算法思想 (5)2.3数据类型的定义 (5)3详细设计和实现 (6)3.1算法流程图 (6)3.2 主程序 (6)3.3 回溯算法程序 (7)4调试与操作说明 (9)4.1调试情况 (9)4.2操作说明 (9)5设计总结 (11)参考文献 (12)附录 (12)1需求分析1.1功能分析八皇后问题是一个古老而著名的问题,该问题是十九世纪著名的数学家高斯1850年提出的,并作了部分解答。
高斯在棋盘上放下了八个互不攻击的皇后,他还认为可能有76种不同的放法,这就是有名的“八皇后”问题。
在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。
所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。
现在我们已经知道八皇后问题有92个解答。
1、本演示程序中,利用选择进行。
程序运行后,首先要求用户选择模式,然后进入模式。
皇后个数设0<n<11。
选择皇后个数后,进入子菜单,菜单中有两个模式可以选择。
2、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令:相应的输入数据和运算结果显示在其后。
3、程序执行的命令包括:1)进入主菜单。
2)选择皇后问题,输入是几皇后。
3)进入子菜单。
4)选择皇后显示模式。
5)选择结束4、测试数据1)N的输入为4;2)共有2个解答。
3)分别是○●○○○○●○○○○●●○○○●○○○○○○●○○●○○●○○1.2设计平台Windows2000以上操作系统;Microsoft Visual C++ 6.02概要设计问题:N后问题问题描述:国际象棋中皇后可以攻击所在行,列,斜线上的每一个位置,按照此规则要在一个n*n的棋盘上放n个皇后使每一个皇后都不互相攻击问题分析:引入1个数组模拟棋盘上皇后的位置引入3个工作数组行数组[k]=1,表示第k行没有皇后右高左低数组[k]=1,表示第k条右高左低的斜线上没有皇后左高右低数组[k]=1,表示第k条左高右低的斜线上没有皇后观察棋盘找到规律同一右高左低的斜线上的方格,它们的行号和列号之和相等;同一左高右低的斜线上的方格,它们的行号和列号只差相等;开始时,所有行和斜线上都没有皇后,从第一列的第一行配置第一个皇后开始,在第m列的皇后位置数组[m]行放置了一个合理的皇后之后,准备考察第m+1列时,在数组行数组[],右高左低数组[],左高右低数组[]中为第m列,皇后位置数组[m]的位置设定有皇后标志如果按此放置位置得不到结果,则把当前列中的有皇后标记改为无皇后标记。
八皇后问题(回溯法)

void queen(int N)
{ //初始化N+1个元素,第一个元素不使用
int col[N+1]; //col[m]=n表示第m列,第n行放置皇后
int a[N+1]; //a[k]=1表示第k行没有皇后
int b[2*N+1]; //b[k]=1表示第k条主对角线上没有皇后
int c[2*N+1]; //c[k]=1表示第k条次对角线上没有皇后
int j,m=1,good=1;char awn;
for(j=0;j<=N;j++)
{a[j]=1;}
for(j=0;j<=2*N;j++)
{b[j]=c[j]=1;}
col[1]=1;col[0]=0;
do
{
if(good)
八皇后问题(回溯法)2009-08-11 12:03问题描述:
求出在一个n×n的棋盘上,放置n个不能互相捕捉的国际象棋“皇后”的所有布局,这是来源于国际象棋的一个问题。皇后可以沿着纵横和两条斜线4个方向互相捕捉。
解题思路:
总体思想为回溯法。
求解过程从空配置开始。在第1列~的m列为合理配置的基础上,再配置第m+1列,直至第n列也是合理时,就找到了一个解。在每列上,顺次从第一行到第n行配置,当第n行也找不到一个合理的配置时,就要回溯,去改变前一列的配置。
if(awn=='Q'||awn=='q')
exit(0);
while(col[m]==N) //如果本列试探完毕,则回溯
{
m--; //回溯
a[col[m]]=b[m+col[m]]=c[N+m-col[m]]=1;//标记m列col[m]行处没有皇后(所在行,对角线,次对角线上都没有皇后)
八皇后源代码及流程图
目录一需求分析 (1)1.1程序的功能: (1)1.2程序的输入输出要求: (1)二概要设计 (3)2.1程序的主要模块: (3)2.2程序涉及: (3)三详细设计 (3)3.1相关代码及算法 (4)3.1.1 定义相关的数据类型如下:....................... 错误!未定义书签。
3.1.2 主模块类C码算法: (4)3.1.3 画棋盘模块类C码算法 (5)3.1.4 画皇后模块类C码算法: (5)3.1.5 八皇后摆法模块(递归法): (6)3.1.6 初始化模块 (7)3.1.7 输出摆放好的八皇后图形(动态演示): (7)3.2相关流程图 (9)四调试分析 (12)五设计体会 (13)六附录 (13)七参考文献 (17)一需求分析1.1 程序功能:八皇后问题是一个古老而著名的问题。
该问题是十九世纪著名的数学家高斯1850年提出的。
八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子,问有多少种不同的摆法?并找出所有的摆法。
因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
本程序通过对子函数void qu(int i)的调用,将八皇后的问题关键通过数据结构的思想予以了实现。
虽然题目以及演算看起来都比较复杂,繁琐,但在实际中,只要当一只皇后放入棋盘后,在横与列、斜线上没有另外一只皇后与其冲突,再对皇后的定位进行相关的判断。
即可完成。
如果在这个程序中,我们运用的是非递归的思想,那么将大量使用if等语句,并通过不断的判断,去推出答案,而且这种非递归的思想,大大的增加了程序的时间复杂度。
如果我们使用了数据结构中的算法后,那么程序的时间复杂度,以及相关的代码简化都能取得不错的改进。
这个程序,我运用到了数据结构中的栈、数组,以及树和回溯的方法。
八皇后问题代码实现
八皇后问题代码实现/*代码解析*//* Code by Slyar */ #include <stdio.h>#include<stdlib.h> #define max 8 int queen[max], sum=0; /* max为棋盘最大坐标*/ void show() /* 输出所有皇后的坐标*/{ int i; for(i = 0; i < max; i++){ printf("(%d,%d) ", i, queen[i]); }printf("\n"); sum++;} int check(int n) /* 检查当前列能否放置皇后*/{ int i; for(i = 0; i < n; i++) /* 检查横排和对角线上是否可以放置皇后*/ { /* ///题目的要求是所有皇后不在同一横排、竖排、对角线上。
1、queen[n]值为竖排号,可看为Y轴上值。
n值为横排号,可看为X轴上值。
2、(1)先从横坐标第n点排开始放皇后,再放第n+1,所有不会同一横坐标点即同一竖排。
(2)queen[i] == queen[n]时即y坐标相等,即在同一横排,此时判断不合规则点。
(3)abs(queen[i] - queen[n]) == (n - i),可变形为(queen[n] - queen[i]) /(n - i)==tan45°或tan135° 由公式可得出,点(n,queen[n])与点(i,quuen[i])在同一条左斜线135°或右斜45°,即国际象棋上的每个格子的两条斜角线。
3、由2即可得出当前格式是否能放置一个皇后。
*/ if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == (n - i)) { return1; } } return 0;} void put(int n) /* 回溯尝试皇后位置,n为横坐标*/{ int i; for(i = 0; i < max;i++) { queen[n] = i; /* 将皇后摆到当前循环到的位置*/ if(!check(n)){ if(n == max - 1){ show(); /* 如果全部摆好,则输出所有皇后的坐标*/ } else { put(n + 1); /* 否则继续摆放下一个皇后*/ } } }} int main(){ put(0); /*从横坐标为0开始依次尝试*/ printf("TTTTTT----%d\n", sum); //system("pause"); //while(1); return 0;}/*算法系列---回溯算法引言寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。
C++课程设计八皇后问题
安徽建筑工业学院数据结构设计报告书院系数理系专业信息与计算科学班级11信息专升本学号11207210138姓名李晓光题目八皇后指导教师王鑫1.程序功能介绍答:这个程序是用于解决八皇后问题的。
八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
做这个课题,重要的就是先搞清楚哪个位置是合法的放皇后的位置,哪个不能,要先判断,后放置。
我的程序进入时会让使用者选择程序的功能,选【1】将会通过使用者自己手动输入第一个皇后的坐标后获得答案;选【2】将会让程序自动运算出固定每一个皇后后所有的排列结果。
2.课程设计要求答:(1)增加函数,完成每输入一组解,暂停屏幕,显示“按任意键继续!”。
(2)完善程序,编程计算八皇后问题共有集中排列方案。
(3)增加输入,显示在第一个皇后确定后,共有几组排列。
(4)将每组解的期盼横向排列输出在屏幕上,将五个棋盘并排排列,即一次8行同时输出5个棋盘,同样完成一组解后屏幕暂停,按任意键继续。
(5)求出在什么位置固定一个皇后后,解的数量最多,在什么位置固定皇后后,解的数量最少,最多的解是多少,最少的解是多少,并将最多,最少解的皇后位置及所有的解求出,同样5个一组显示。
3.对课程题目的分析与注释答:众所周知的八皇后问题是一个非常古老的问题,问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击。
按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子。
因此,本课程设计的目的也是通过用C++语言平台在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现。
使用递归方法最终将其问题变得一目了然,更加易懂。
首先要用到类,将程序合理化:我编辑了一个盘棋8*8的类:class Board,还有个回溯法的类:class Stack,关键的类好了,然后编辑好类的成员,然后编辑主函数利用好这些类的成员,让其运算出结果。
用CSP(约束满足问题)方法解决八皇后问题
conflictNum++; } } //检查同一列是否有冲突 j=column; for(i=0;i<N;i++) { if((i!=row)&&(queenBoard[i][j]==QUEEN)) {
//如果同一列其它位置有皇后,记录冲突点数 conflictNum++; } } //检查'\'斜线是否有冲突 if(row>column) { i=row-column; j=0; } else { i=0; j=column-row; } for(;(i<N)&&(j<N);i++,j++ ) { if((i!=row)&&(queenBoard[i][j]==QUEEN)) { //如果'\'斜线其它位置有皇后,记录冲突点数 conflictNum++; } } //检查'/'斜线是否有冲突 if((row+column)<N) { i=row+column; j=0; } else { i=N-1; j=row+column-N+1; } for(;(i>=0)&&(j<=N);i --,j++)
该列的每一行中与该位置有冲突的皇后数,选取冲突数最小的位置作为新的该列的皇后位置, 并记录下该列被放置皇后的信息,记录被放置皇后信息的目的是为了避免算法陷入死循环。
为了更清楚地说明该算法,假设算法某一步搜索到的状态如下:
此时按照最小冲突算法,第二列、第六列、第七列和第八列的皇后 有冲突,则当计算第六列 的每一行的与该位置有冲突的皇后数时,结果如下:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
xxxx《数据结构与算法》课程设计报告课程设计题目八皇后问题院系名称计算机科学与技术系专业(班级)姓名(学号)指导教师完成时间一、问题分析和任务定义此部分包括以下四部分内容分析问题概述,问题规定的输入和输出形式,算法的功能,测试数据,设计任务1.1问题概述八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。
该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
考虑到8*8棋盘总共64格,而且根据条件每行每列只可能有1个皇后。
在这种情况下,可以先固定第一个皇后,然后根据条件固定下一个皇后所在位置,依次类推,当符合条件的8个皇后确定了以后就输出这一组解。
从程序算法上来实现的话就要使用递归函数。
高斯认为有76种方案。
1854年在柏林的象棋杂志上不同的作者发表了47种不同的解,后来有人用图论的方法解出92种结果。
事实上就是有92种解法。
此问题要求在一个8*8的棋盘上放置8个皇后,使得他们彼此不受“吃掉”。
按照国际象棋的规则,一个皇后可以攻击与其处与同一行,同一列,同一斜线的其他棋子,八皇后问题要求出在棋盘上放置这8个皇后的方案。
(1)由于国际象棋中皇后可以直吃、横吃、对角线吃,所以新输入棋盘中的皇后(新皇后),可能就被先放置的皇后(老皇后)吃掉。
(2)本题要求在在8*8国际象棋棋盘上,放置八个皇后,使得八个棋子不能互相被对方吃掉。
具体要求:a.依次输出各种成功的放置方法。
b.最好能画出棋盘的图形形式,并在其动态地标注行走的过程。
c.程序能方便地移植到其他规格的棋盘上。
(3)本设计将以整型输入输出,将会将八皇后成功的放置方法输出。
(4)画一个8*8棋盘,利用矩阵的方式把8*8的棋盘格式输出。
1.2问题规定的输入和输出形式:1.2.1输入为所要求摆放皇后的个数,题义为八个皇后,所以输入形式为整形输入。
1.2.2 输出为摆放矩阵形式,用Q代表皇后,*代表棋盘,所以输出形式为字符型,并且用矩阵形式输出。
下图1为八皇后摆放的其中一种方案。
图1是8-皇后问题的一个可行解(图中Q代表皇后)。
NO. 2 method.Q * * * * * * ** * * * * Q * ** * * * * * * Q* * Q * * * * ** * * * * * Q ** * * Q * * * ** Q * * * * * ** * * * Q * * *图1. 八皇后第二种摆法1.3算法(程序)所能达到的功能本设计预将八皇后(即8个棋子)不在同一行、同一列、或者同一对角线在8*8的国际象棋棋盘上用矩阵的方法摆放出来,并且求出摆放的解法总数。
以“穷举法”和“递归法”来解八皇后问题。
1.4 测试用的数据(包括正确的输出)输入要求解的皇后个数-8:从八皇后摆放的第1~92种解法中的任几种摆法(如14,15,80,81种)并求解其中的摆法。
1.5 设计任务设计一个程序来将所有的把8-皇后成功放置在棋盘上的解法通过一定的形式表现出来。
二、概要设计和数据结构的选择此部分包括三个内容分析:算法的数据类型定义,程序的主流程图,每个模块的调用关系。
1.算法(程序)中用到的所有各种数据类型的定义1.1 程序中定义了一个一维数组,queen[],对皇后位置存放进行判别;定义int i,统计比较的次数;定义int c,统计摆放的皇后总数1.2 调用Trial()函数,表示对从第0行开始判断,当判断过8行,并且棋盘布局合格,则开始打印整个摆法。
1.3 用到getch()函数,程序结果太多,通过这个函数来逐个显示各种摆法。
2.流程图:下图2 八皇后流程图图2。
八皇后流程图3.各模块的调用关系3.1主函数中调用Trial()函数,判断每行棋盘摆放是否合法,合法则打印。
3.2 在Trial()函数中调用check()函数,看每一行的摆放方法是否合法。
3.3 通过调用check()函数,判断是否返回为1,返回0就执行下一次循环。
若返回1就再次调用Trial()函数,进行下次判别。
设计中用穷举法和递归算法解决问题。
解决这个问题可能涉及到循环结构,选择结构,一维数组和指针,以及一些必要的数学函数。
循环结构:for循环语句。
选择结构:if选择语句。
三、详细设计和编码此部分包括以下两部分内容分析:算法数据类型和表示形式,算法各模块的实现1.算法数据类型和表示形式1.1 算法数据类型int queen[]; /*用一维数组queen[]来存储序列*/int c;/*统计摆放的皇后总数*/int i /*统计比较的次数*/3.1.2 八皇后的摆放形式8个皇后各占一行,穷举每一行上可能占有的列,再排除不合条件的情况,只输出合理的解。
八皇后问题的表示:通过矩阵的方式将其表现出来,如图3(Q表示皇后,*表示棋盘里的其他棋子)Q * * * * * * ** * * * * Q * ** * * * * * * Q* * Q * * * * ** * * * * * Q ** * * Q * * * ** Q * * * * * ** * * * Q * * *图3 八皇后的第1种摆法2 算法各模块的实现2.1 main()函数:在主函数中先定义int queen[] ,数组queen[]来存储序列,赋初值。
并在主函数中调用Trial()函数,判断八行皇后摆法格局都合法,合法则调用打印函数。
最终输出八皇后摆法的总数。
2.2 Trial()函数:是对八行皇后摆法格局都合法性进行判断,用全局变量i,控制比较的次数,若Q放在第0行的首位置,再判断第二行的Q是否和它是否会“攻击”,逐个判断其他行是否会和它发生冲突,当再次调用Trial()函数时,i增加1,就判断Q放在第0行的第1个位置时,逐行判断和其他行的Q是否冲突。
依次循环下去,直到比较出所有的布局都合法,就开始打印摆法。
具体实现如下:void Trial(int queens[], int i, int n) //当判断皇后摆法都合法时,打印棋盘if (i >= n){c ++;PrintTheChessBoard(queens, n);//调用PrintTheChessBoard()函数,打印皇后}else{ int j;for (j = 0; j < n; j ++){queens[i] = j;//对queen数组从新赋值if(CheckTheChessBoard(queens, i)) //调用CheckTheChessBoard函数,若返回数为1,就再次调用Trial函数{ Trial(queens, i + 1, n);}}}}2.3 Checkchessboard()函数:用于对棋盘格式的判断,当Q在同一行,同一列或者同一对角线上时,就发生冲突。
主要就是通过if(j != k && (queens[j] == queens[k]||abs(queens[j] - queens[k]) == abs(j - k)))判断是否合法,若合法就返回1,不合法就返回0。
具体实现如下:int CheckTheChessBoard(int queens[], int i) {// 检查棋盘从第0 行到第i 行的布局是否合法int j, k;for (j = 0; j <= i; j ++) { //循环控制for (k = 0; k <= i; k ++){ //循环控制if (j != k && (queens[j] == queens[k]||abs(queens[j] - queens[k]) == abs(j - k))) //判断是否在对角线上//判断皇后是否在同一行//判断皇后是否在同一列上{ return 0;//若在同一行,同一列或者同一对角线上,返回0 } }} return 1;//若在同一行,同一列或者同一对角线上,返回1}2.4 PrintTheChessBoard()函数是用于对摆法的打印,当i>=8时,说明已经比较完,且布局合法,打印八皇后的摆法。
具体实现如下:void PrintTheChessBoard(int queens[], int n){ //打印棋盘int i, j;//控制循环printf("NO. %d method.\n",c); //输出第num种摆法for (i = 0; i < n; i ++){//控制循环for (j = 0; j < queens[i]; j ++){printf(" *");//打印*棋子}printf(" Q");//打印皇后for (j = n-1; j > queens[i]; j --){printf(" *");//打印*棋子};putchar('\n');//换行}printf("Please press enter to see the next answer\n\n");//按回车键输出下个方案getch();//从键盘获取字符}2.5 具体描述试探安排八个皇后,从第0行开始,逐步安排每行皇后。
对于每个皇后(设为第i个),都是从第一列开始寻找位置,逐个查找直到找到正确的位置(设为第j列,则A[j]、B[i+j]、C[i-j+7]都没有被占用)为止。
如果找到了一个合适的位置,则标记A[j]、B[i+j]、C[i-j+7]为被占用状态,并继续安排下一个皇后(第i+1个);否则,如果找不到合适位置,则说明前面的安排不太合理,应该退回到第i-1行的皇后,重新安排。
如果8个皇后都安排好了,则输出这种方案。
为了找到其它方案,应该回溯,重新试探第7个(最后一个)皇后的下一种安排方法。
在回溯的过程中,应该抹掉前面试探留下的标记,即恢复A[j]、B[i+j]、C[i-j+7]为未被占用状态,这样才能正确地开展下一步的试探。
不管是找到了解还是没有找到解都必须抹掉以前的标记,并回溯。
这种回溯过程将逐步返回,使得各行的皇后都能试探到各种可能的摆法四、上机调试此部分包括三个内容分析:程序调试问题分析,算法分析,对设计的算法分析和改进。
心得分析。
1.程序调试问题分析:问题1:经过调试,在输出的屏幕上为多一列,与条件不相符合,主要是for (j = n; j > queens[i]; j --) 中对j赋予初值时j=n,所以多输出一列。
原因:在程序中定义了queen[]来存储序列的,在搜索过程中搜索的是每一行,其下标为0~7,若j=n,则会多输出一列。