八皇后问题 C语言程序设计
八皇后问题c语言代码讲解
![八皇后问题c语言代码讲解](https://img.taocdn.com/s3/m/734dd7b805a1b0717fd5360cba1aa81144318fb9.png)
八皇后问题c语言代码讲解八皇后问题是一个经典的回溯算法问题,要求在一个8x8的棋盘上放置8个皇后,使得它们互不攻击,即任意两个皇后都不能在同一行、同一列或同一对角线上。
下面是一个使用C语言实现八皇后问题的代码示例:c.#include <stdio.h>。
#define N 8。
int board[N][N];// 检查当前位置是否安全。
int isSafe(int row, int col) {。
int i, j;// 检查当前列是否有皇后。
for (i = 0; i < row; i++) {。
if (board[i][col] == 1) {。
return 0;}。
}。
// 检查左上对角线是否有皇后。
for (i = row, j = col; i >= 0 && j >= 0; i--, j--) {。
if (board[i][j] == 1) {。
return 0;}。
}。
// 检查右上对角线是否有皇后。
for (i = row, j = col; i >= 0 && j < N; i--, j++) {。
if (board[i][j] == 1) {。
return 0;}。
}。
return 1;}。
// 在当前行放置皇后。
int solve(int row) {。
int col;// 所有行都放置完毕,打印结果。
if (row == N) {。
for (int i = 0; i < N; i++) {。
for (int j = 0; j < N; j++) {。
printf("%d ", board[i][j]); }。
printf("\n");}。
printf("\n");return 1;}。
// 逐列尝试放置皇后。
for (col = 0; col < N; col++) {。
八皇后问题
![八皇后问题](https://img.taocdn.com/s3/m/719e23dd33d4b14e85246823.png)
计算机科学与技术专业数据结构课程设计报告设计题目:八皇后问题目录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]的位置设定有皇后标志如果按此放置位置得不到结果,则把当前列中的有皇后标记改为无皇后标记。
回溯法解八皇后问题
![回溯法解八皇后问题](https://img.taocdn.com/s3/m/316197ed856a561252d36f4f.png)
fprintf(fp," ");
}
printf("%d\n", i);
fprintf(fp, "%d\n", i);
}
printf
(".......................................................\n");
fprintf(fp,
/*/
#include <stdio.h>
#include <math.h>
#define false 0
#define true 1
#define quesize 8
int gx[quesize+1];
int sum=0;
int place( int k );
void print( int a[] );
fprintf(fp,"the sum of the ways of queens:%d\n", sum);
printf("the sum of the ways of queens:%d\n", sum);
fclose(fp);
return 1;
}
/*/////////////////////////////////////////////////////////////////////
{
int i = 1;
while ( i < k )
{ if ( ( gx[i] == gx[k] ) || ( abs( gx[i] - gx[k] )==abs( i - k ) )
八皇后源代码及流程图
![八皇后源代码及流程图](https://img.taocdn.com/s3/m/3f4b50791711cc7931b71658.png)
目录一需求分析 (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等语句,并通过不断的判断,去推出答案,而且这种非递归的思想,大大的增加了程序的时间复杂度。
如果我们使用了数据结构中的算法后,那么程序的时间复杂度,以及相关的代码简化都能取得不错的改进。
这个程序,我运用到了数据结构中的栈、数组,以及树和回溯的方法。
八皇后问题代码实现
![八皇后问题代码实现](https://img.taocdn.com/s3/m/203d85af69dc5022aaea00e3.png)
八皇后问题代码实现/*代码解析*//* 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++课程设计八皇后问题
![C++课程设计八皇后问题](https://img.taocdn.com/s3/m/5d71d81cff00bed5b9f31db5.png)
安徽建筑工业学院数据结构设计报告书院系数理系专业信息与计算科学班级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,关键的类好了,然后编辑好类的成员,然后编辑主函数利用好这些类的成员,让其运算出结果。
八皇后说明书
![八皇后说明书](https://img.taocdn.com/s3/m/47ab7d2b7375a417866f8fa1.png)
目录摘要 (1)前言 (2)正文 (3)1.采用类C语言定义相关的数据类型 (3)2.各模块的伪码算法 (3)3.函数的调用关系图 (6)4.调试分析 (7)5.测试结果 (7)6.源程序(带注释) (10)总结 (12)参考文献 (13)致谢 (14)摘要此程序主要是实现国际象棋“八皇后”的问题。
在一个8 * 8 的棋盘上,放置八个皇后,而每个皇后之间不相互攻击。
即每行只能放一个皇后,而且每列只能放置一个皇后,每个斜行只能放一个皇后。
根据这种规定,可在8 * 8 的棋盘上实现不同的92中放法。
这个程序就根据递归算法,用简单的代码实现皇后的放法。
本次设计旨在学习各种算法,训练对基础知识和基本方法的综合运用及变通能力,增强对算法的理解能力,提高软件设计能力。
在实践中培养独立分析问题和解决问题的作风和能力。
要求熟练运用C语言、基本算法的基础知识,独立编制一个具有中等难度的、解决实际应用问题的应用程序。
通过对题意的分析与计算,用递归法回溯法及枚举法解决八皇后是比较适合的。
递归是一种比较简单的且比较古老的算法。
此外还有回溯法是递归法的升华,在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。
而枚举法,更是一种基础易懂简洁的方法。
而今天所用的算法只是递归算法。
不论用什么法做这个课题,重要的就是先搞清楚哪个位置是合法的放皇后的位置,哪个不能,要先判断,后放置。
关键词:八皇后;算法设计;递归算法设计;数组前言国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。
所以高斯提出了一个问题:在8 * 8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。
这个问题是十九世纪著名的数学家高斯1850年提出的。
高斯认为有76种方案。
1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
回溯法解决8皇后问题实验报告
![回溯法解决8皇后问题实验报告](https://img.taocdn.com/s3/m/c5eaf010c5da50e2524d7fce.png)
算法设计与分析实验报告实验名称:用回溯法解决八皇后问题姓名:学号:江苏科技大学一、实验名称:回溯法求解8皇后问题二、学习知识:回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
回溯法是一个既带有系统性又带有跳跃性的搜索算法。
它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解的空间树。
算法搜索至解的空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。
如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。
否则,进入该子树,继续按深度优先的策略进行搜索。
回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。
而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。
三、问题描述(1)使用回溯法解决八皇后问题。
8皇后问题:在8*8格的棋盘上放置彼此不受攻击的8个皇后。
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
8后问题等价于在8*8格的棋盘上放置8个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
(2)用高级程序设计语言实现四、求解思路Procedure PLACE(k)//如果一个皇后能放在第k行和X(k)列,则返回true,否则返回false。
X是一个全程数组,进入此过程时已置入了k个值。
ABS(r)过程返回r的绝对值//global X(1:k); integer i,k;i←1while i<k doif X(i)=X(k) or ABS(X(i)-X(k))=ABS(i-k) thenreturn (false)end ifi←i+1repeatreturn (true)End PLACEProcedure NQUEENS(n)//此过程使用回溯法求出一个n*n棋盘上放置n个皇后,使其不能互相攻击的所有可能位置//integer k,n,X(1:n)X(1)←0 ; k←1 // k是当前行;X(k)是当前列 //while k>0 do // 对所有的行,执行以下语句 //X(k)←X(k)+1 //移到下一列//while X(k)<=n and Not PLACE(k) do //此处能放这个皇后吗//X(k)←X(k)+1 //不能放则转到下一列//repeatif X(k)<=n then //找到一个位置//if k=n then print (X) //是一个完整的解则打印这个数组// else k←k+1;X(k)←0 //否则转到下一行//end ifelse k←k-1 //回溯//end ifrepeatEnd NQUEENS五、算法实现本实验程序是使用C#编写,算法实现如下:1.queen类—实现8皇后问题的计算,将结果存入数组。
八皇后问题的解决完整
![八皇后问题的解决完整](https://img.taocdn.com/s3/m/0822c9790508763230121249.png)
八皇后问题的解决完整 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)使用数据结构的知识,用递归法解决问题。
C语言回溯法解八皇后问题(八皇后算法)
![C语言回溯法解八皇后问题(八皇后算法)](https://img.taocdn.com/s3/m/b0a83a60f56527d3240c844769eae009581ba20b.png)
C语⾔回溯法解⼋皇后问题(⼋皇后算法)⼋皇后问题(N皇后问题)的回溯法求解⼀、问题描述在⼀个国际象棋棋盘上放置⼋个皇后,使得任何两个皇后之间不相互攻击,求出所有的布棋⽅法,并推⼴到N皇后情况。
⼆、参考资料啥⽂字都不⽤看,B站上有个⾮常详细的动画视频解说,上链接三、源代码#include<iostream>#include<vector>#include<string>using namespace std;void put_queen(int x, int y, vector<vector<int>>&attack){//实现在(x,y)放置皇后,对attack数组更新,xy表⽰放置皇后的坐标,attack表⽰是否可以放置皇后//⽅向数组,⽅便后⾯对8个⽅向进⾏标记static const int dx[] = { -1,-1,-1,0,0,1,1,1 };static const int dy[] = { -1,0,1,-1,1,-1,0,1 };attack[x][y] = 1;//将皇后位置标记为1//通过两层for循环,将该皇后可能攻击到的位置标记for (int i = 1; i < attack.size(); i++)//从皇后位置向1到n-1个距离延伸{for (int j = 0; j < 8; j++)//遍历8个⽅向{int nx = x + i * dx[j];//⽣成的新位置⾏int ny = y + i * dy[j];//⽣成的新位置列//在棋盘范围内if (nx >= 0 && nx < attack.size() && ny >= 0 && ny < attack.size())attack[nx][ny] = 1;//标记为1}}}//回溯算法//k表⽰当前处理的⾏//n表⽰n皇后问题//queen存储皇后的位置//attack标记皇后的攻击范围//solve存储N皇后的全部解法void backtrack(int k, int n, vector<string>& queen,vector<vector<int>>& attack,vector<vector<string>>& solve){if (k == n)//找到⼀组解{solve.push_back(queen);//将结果queen存储⾄solvereturn;}//遍历0⾄n-1列,在循环中,回溯试探皇后可放置的位置for (int i = 0; i < n; i++){if (attack[k][i] == 0)//判断当前k⾏第i列是否可以放置皇后{vector<vector<int>> tmp = attack;//备份attack数组queen[k][i] = 'Q';//标记该位置为Qput_queen(k, i, attack);//更新attack数组backtrack(k + 1, n, queen, attack, solve);//递归试探k+1⾏的皇后的位置attack = tmp;//恢复attack数组queen[k][i] = '.';//恢复queen数组}}}vector<vector<string>>solveNQueens(int n){//string存储具体的摆放位置,<vector<string>>存放⼀种解法,⼆维vector存放全部解法vector<vector<string>>solve;//存储最后结果vector<vector<int>>attack;//标记皇后的攻击位vector<string>queen;//保存皇后位置//使⽤循环初始化attack和queen数组for (int i = 0; i < n; i++){attack.push_back((vector<int>()));for (int j = 0; j < n; j++){attack[i].push_back(0);}queen.push_back("");queen[i].append(n, '.');}backtrack(0, n, queen, attack, solve);return solve;//返回结果数组}int main(){//int num;//cin >> num;//输⼊皇后数初始化attack数组//vector<vector<int>> attack(num,vector<int>(num, 0));初始化queen数组//string s;//for (int i = 0; i < num; i++)s += '.';//vector<string> queen(num, s);int n;cin >> n;vector<vector<string>>result;result = solveNQueens(n);cout << n << "皇后共有" << result.size() << "种解法" << endl;for (int i = 0; i < result.size(); i++){cout << "解法" << i + 1 << ":" << endl;for (int j = 0; j < result[i].size(); j++){cout << result[i][j] << endl;}cout << endl;}system("pause");return 0;}四、测试结果四皇后⼋皇后到此这篇关于C语⾔回溯法解⼋皇后问题的⽂章就介绍到这了。
八皇后问题的解决完整
![八皇后问题的解决完整](https://img.taocdn.com/s3/m/69ceba039b89680202d82539.png)
Standardization ofsany group #QS8QHH-HHGX8Q8-GNHHJ8-HHMHGN#■ •・・WAS 1 ■ ■ ■数据结构课程设计报告设计题目: __________ 八皇后_______________________________________2008 年6 月25 日设计任务书指导教师(签章):2008 年6 月30 日摘要:八皇后问题要求在一个8 * 8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
而本课程设计本人的目的也是通过用C++语言平台将一个8 * 8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.使用递归方法最终将其问题变得一目了然,更加易懂。
关键词:八皇后;C++ ;递归法1.课题综述1.1课题的来源及意义八皇后问题是一个古老而着名的问题,该问题是十九世纪着名的数学家高斯1850年提出的。
在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。
所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。
到了现代,随着计算机技术的飞速发展,这一古老而有趣的数学游戏问题也自然而然的被搬到了计算机上。
运用所学计算机知识来试着解决这个问题是个锻炼和提高我白己编程能力和独立解决问题能力的好机会,可以使我增强信心,为我以后的编程开个好头,故我选择了这个有趣的课题。
1.2面对的问题1)解决冲突问题:这个问题包括了行,列,两条对角线;列:规定每一列放一个皇后,不会造成列上的冲突;行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;2)使用数据结构的知识,用递归法解决问题。
八皇后问题(递归+非递归)
![八皇后问题(递归+非递归)](https://img.taocdn.com/s3/m/b0a025fdc8d376eeaeaa3193.png)
八皇后问题(递归+非递归)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;}。
八皇后问题
![八皇后问题](https://img.taocdn.com/s3/m/c3562729bd64783e09122bf1.png)
{
int i;
//!输出序号。
printf("No.%-5d" , ++iCount);
//!依次输出各个列上的皇后的位置,即所在的行数。
for(i = 0 ; i < QUEENS ; i++)
printf("%d " , Site[i]);
for(j=0;j<8;j++)
{
Result += N_Queens(i,j,Queens+1);
if(Result>0)
br0)
return 1;
else
{
Chessboard[LocX][LocY] = 'X';
for(i = 1 ; i <= QUEENS ; i++)
{
//!在该列的第i行上放置皇后。
Site[n] = i;
//!如果放置没有冲突,就开始下一列的试探。
if(IsValid(n))
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
if(Chessboard[i][j] == 'Q')
printf("(%d,%d)n",i,j);
}
getch();
}
/*********************************************************
if(Chessboard[i--][j++] != 'X')
八皇后游戏
![八皇后游戏](https://img.taocdn.com/s3/m/b1fdaf207375a417866f8fdd.png)
CDC *pDC,dc; pDC=GetDC(); CBitmap picture1,picture2; picture1.LoadBitmap(IDB_BITMAP1);//加载位图 picture2.LoadBitmap(IDB_BITMAP2); dc.CreateCompatibleDC(NULL); int i,j; for(i=0; i<width; i++)//绘制棋盘 #43;+) {
if((i+j)%2==0) {
dc.SelectObject(picture1);
pDC->BitBlt(j*nSize,i*nSize,(j+1)*nSize,(i+1)*nSize,&dc,0,0,SRCCOPY);
} else {
dc.SelectObject(picture2);
3、模块设计
八 皇 后 游 戏
绘制面板 添加鼠标点击响应函数
算法判断并刷新面板
4、流程图
开始
选择难度
否
难度 1
是
绘制 4 皇后棋盘
难度 2
否
是
绘制 6 皇后棋盘
难度 3
否
是
绘制 8 皇后棋盘
开始玩游戏
否
是否成功
是
否
时间是否 用完
是 结束
5、功能实现设计
(1)绘制面板
void CMy8queenDlg::Drawimage(int width) {
if(image[i][j]==1) {
count++; } } } if(count==flag) { AfxMessageBox("祝贺你获得胜利!",MB_OK); }
用遗传算法解八皇后问题
![用遗传算法解八皇后问题](https://img.taocdn.com/s3/m/e9c16c0277c66137ee06eff9aef8941ea76e4b6e.png)
⽤遗传算法解⼋皇后问题此算法收敛速度还可以,基本在1万代之内就能找到解主程序clear;clc;%%%⼋皇后问题,8X8的棋盘上,放置8个皇后,使之两两都不能攻击%初始的状态,随机在棋盘上放置8个皇后,每列放⼀个n = 8; %8皇后%%%⽤遗传算法计算%先随机获得⼏个个体,形成⼀个种群%这个种群有10个个体No_of_people = 10;people = randi(n,[No_of_people,n]);%计算每个初始种群的h值people_h = ones(No_of_people,1);for i = 1:No_of_peoplepeople_h(i) = fun_c(people(i,:));end%进化了多少代,由G来统计G = 1;G_max = 1e5;plt = zeros(1,G_max);while prod(people_h)~=0 && G<=G_max%精英保留策略,保留初始种群中1/100的精英个体%保留多少个精英No_elite = fix(No_of_people/100);if No_elite == 0No_elite =1;end%按照h值选出这些精英[~,ind] = sort(people_h);index = ind(1:No_elite);people_elite = people(index,:);%计算这个种群中每个个体的优势,以百分⽐表⽰,所有个体优势之和为1adv = people_h ./ sum(people_h);%从种群中随机选出10对个体,根据个体的优势来选择,优势越⼤的,被选中的概率越⼤people_dad = people;people_mom = people;for i=1:No_of_peoplepick = ones(2,1);while pick(1)==pick(2)pick = randsrc(2,1,[1:No_of_people; adv']);endpeople_dad(i,:) = people(pick(1),:);people_mom(i,:) = people(pick(2),:);end%然后交叉繁殖,染⾊体交叉。
约瑟夫环与八皇后问题--数据结构课程设计实验报告
![约瑟夫环与八皇后问题--数据结构课程设计实验报告](https://img.taocdn.com/s3/m/116a716e783e0912a2162a48.png)
录 问题描述 1 问题分析 1 数据结构描述 算法设计 2 详细程序清单 程序运行结果 心得体会 12
1 4 11
一、 问题描述 1. 约瑟夫问题描述 编号为1,2... n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一 开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报 数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的 下一个开始重新从1报数,如此下去,直至所有人全部出列为止,设计一个程序求出出列 顺序。 2. 八皇后问题描述 在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相"冲"(在每一横 列竖列斜列只有一个皇后)。 3、界面设计模块问题描述 设计一个菜单式界面,让用户可以选择要解决的问题,同时可以退出程序。界面要 简洁明了,大方得体,便于用户的使用,同时,对于用户的错误选择可以进行有效的处 理。 二、 问题分析 在整个课程设计中,我主要负责的是约瑟夫问题中链表中的出列的操作算法的设计。 用循环单链表表示编号为1,2... n的n个人按顺时针方向围坐一圈,每人持有一个密码 (正整数)。一开始输入一个正整数作为报数的上限值turn,从第一个人开始按顺时针方 向自1开始顺序报数(即从第一个结点开始指针向后移动),报到turn-1时(即指针指向 turn-1个结点时)停止,他的下一位出列,将他的下一位密码作为新的turn值,从出列的 人的的顺时针方向上的下一个开始重新从1报数,如此下去,直至链表中只剩一位(即一 个结点)退出循环,并所有人的编号按出列顺序输出。在实现的过程中定义i表示报数的
int code; struct LNode *next; }node,*linklist; linklist creatstart(linklist L,int number) { int m,i; linklist s,p; s=L; for(i=1;i<=number;i++) { p=(linklist)malloc(sizeof(node)); if(!p) exit(0); p->data=i; printf("please input the code of number %d:",i); scanf("%d",&p->code); p->next=NULL; s->next=p; s=p; } s->next=L->next; return s; } void chulie(linklist L,int number) { int turn,i,j; linklist p,s; printf("please input the start code:"); scanf("%d",&turn); p=L; printf("the turn out of the circle is:"); for(i=1;i<=number-1;i++) { for(j=1;j<=turn-1;j++) p=p->next; printf("%d ",p->next->data); turn=p->next->code; s=p->next; p->next=s->next; free(s); } printf("%d ",p->next->data); printf("\n"); } void lianbiao() { int number; linklist L; L=(linklist)malloc(sizeof(node));
八皇后问题C 解决办法
![八皇后问题C 解决办法](https://img.taocdn.com/s3/m/8f03e03b482fb4daa58d4b74.png)
return true; }
void displayqueen(vector<int> x, int N, int kind) {
if(kind == 1) {
cout<<"第"<<sum<<"个解:";
for(int i=1; i<N+1; i++) {
x[t] = i;
if(place(t, x)) {
backtrack(t+1, x, N, kind); } } } }
bool place(int k, vector<int> x) {
for(int j=1; j<k; j++) {
if((abs(k-j) == abs(x[k]-x[j])) || (x[k] == x[j])) {
for(i=1; i<N+1; i++) {
for(int j=1; j<N+1; j++) {
S[i][x[i]] = 1; } }
cout<<"第"<<sum<<"个解:"<<endl;
for(i=1; i<N+1;ห้องสมุดไป่ตู้i++) {
for(int j=1; j<N+1; j++) {
cout<<S[i][j]<<' '; } cout<<endl; } } }
1213:八皇后问题
![1213:八皇后问题](https://img.taocdn.com/s3/m/78c5b83def06eff9aef8941ea76e58fafab0455c.png)
1213:⼋皇后问题⾸先可以试图去简化问题,将问题转化为为每⼀列确定⼀个有效的⾏号。
因为同⼀列只能有⼀个皇后,并且需要在⼋列中确定⼋个皇后,即每⼀列都必定有且只有⼀个皇后。
经过简化后,显然,通过⼀个⼀维数组即可以确定⼀组有效解。
关于check:不为同⼀⾏或同⼀列的判定⽐较简单(这⾥省略)(i1,j1)与(i2,j2)在同⼀条斜线上的判定:i1-i2==j1-j2 || i1-i2==j2-j1问题经过这样⼀次抽丝剥茧后,剩余的思路⼤致就是深度搜索、临界输出。
特别重复:a[j]表⽰第j列的皇后所在的⾏数1 #include<iostream>2 #include<cstdio>3using namespace std;45const int N=10;6int ans,a[N];7void print(){8 printf("No. %d\n",++ans);9for(int i=1;i<=8;i++){10for(int j=1;j<=8;j++)11if(a[j]==i)printf("1 ");12else printf("0 ");13 printf("\n");14 }15 }16bool check(int x,int d){17for(int i=1;i<d;i++){18if(a[i]==x||x-a[i]==d-i||x-a[i]==i-d)19return0;20 }21return1;22 }23void solve(int d){24if(d==9){25 print();26return;27 }28for(int i=1;i<=8;i++){29if(check(i,d)){30 a[d]=i;31 solve(d+1);32 }33 }34 }35int main(){36 solve(1);37return0;38 }。
C语言八皇后问题
![C语言八皇后问题](https://img.taocdn.com/s3/m/276dce95294ac850ad02de80d4d8d15abe23008e.png)
C语言八皇后问题C语言八皇后问题八皇后问题是一个古老而著名的问题。
该问题是19世纪著名的数学家高斯1850年提出:在一个8*8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后之间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。
问共有多少种不同的方法?回溯算法也叫试探法,它是一种搜索问题的解的方法。
冋溯算法的基本思想是在一个包含所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任意结点时,总是先判断该结点是否肯定不包含问题的解。
如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。
否则,进入该子树,继续按深度优先的策略进行搜索。
回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。
八皇后问题有很多中解法,其中使用回溯法进行求解是其中一种。
而回溯发也是最直接的一种解法,也较容易理解。
八皇后问题的回溯法算法,可以采用一维数组来进行处理。
数组的下标i表示棋盘上的第i列,a[i]的值表示皇后在第i列所放的位置。
例如,a[1]=5,表示在棋盘的第例的第五行放一个皇后。
程序中首先假定a[1]=1,表示第一个皇后放在棋盘的第一列的第一行的位置上,然后试探第二列中皇后可能的位置,找到合适的位置后,再处理后续的各列,这样通过各列的反复试探,可以最终找出皇后的全部摆放方法。
八皇后问题可以使用回溯法进行求解,程序实现如下:#include#define Queens 8 //定义结果数组的大小,也就是皇后的数目int a[Queens+1]; //八皇后问题的皇后所在的行列位置,从1幵始算起,所以加1int main(){int i, k, flag, not_finish=1, count=0;//正在处理的.元素下标,表示前i-1个元素已符合要求,正在处理第i个元素i=1;a[1]=1; //为数组的第一个元素赋初值printf("The possible configuration of 8 queens are:\n");while(not_finish){ //not_finish=l:处理尚未结束while(not_finish && i<=Queens){ //处理尚未结束且还没处理到第Queens个元素for(flag=1,k=1; flag && kif(a[k]==a[i])flag=0;for (k=1; flag&&kif( (a[i]==a[k]-(k-i)) || (a[i]==a[k]+(k-i)) )flag=0;if(!flag){ //若存在矛盾不满足要求,需要重新设置第i个元素if(a[i]==a[i-1]){ //若a[i]的值已经经过一圈追上a[i-1]的值i--; //退回一步,重新试探处理前一个元素if(i>1 && a[i]==Queens)a[i]=1; //当a[i]为Queens时将a[i]的值置1elseif(i==1 && a[i]==Queens)not_finish=0; //当第一位的值达到Queens时结束elsea[i]++; //将a[il的值取下一个值}else if(a[i] == Queens)a[i]=1;elsea[i]++; //将a[i]的值取下一个值}else if(++i<=Queens)if(a[i-1] == Queens )a[i]=1; //若前一个元素的值为Queens则a[i]=lelsea[i] = a[i-1]+1; //否则元素的值为前一个元素的下一个值}if(not_finish){++count;printf((count-1)%3 ? "\t[%2d]:" : "\n[%2d]:", count);for(k=1; k<=Queens; k++) //输出结果printf(" %d", a[k]);if(a[Queens-1]a[Queens-1]++; //修改倒数第二位的值elsea[Queens-1]=1;i=Queens -1; //开始寻找下一个满足条件的解}}}输出结果:The possible configuration of 8 queens are:[ 1]: 1 5 8 6 3 7 2 4 [ 2]: 1 6 8 3 7 4 2 5 [ 3]: 1 7 4 6 8 2 5 3 [ 4]: 1 7 5 8 2 4 6 3 [ 5]: 2 4 6 8 3 1 7 5 [ 6]: 2 5 7 1 3 8 6 4 [ 7]: 2 5 7 4 1 8 6 3 [ 8]: 2 6 8 3 1 4 7 5 [ 9]: 2 6 1 7 4 8 3 5 [10]: 2 7 3 6 8 5 1 4 [11]: 2 7 5 8 1 4 6 3 [12]: 2 8 6 1 3 5 7 4 [13]: 3 5 7 1 4 2 8 6 [14]: 3 5 8 4 1 7 2 6 [15]: 3 5 2 8 1 7 4 6 [16]: 3 5 2 8 6 4 7 1 [17]: 3 6 8 1 4 7 5 2 [18]: 3 6 8 1 5 7 2 4 [19]: 3 6 8 2 4 1 7 5 [20]: 3 6 2 5 8 1 7 4 [21]: 3 6 2 7 1 4 8 5 [22]: 3 6 2 7 5 1 8 4 [23]: 3 6 4 1 8 5 7 2 [24]: 3 6 4 2 8 5 7 1 [25]: 3 7 2 8 5 1 4 6 [26]: 3 7 2 8 6 4 1 5 [27]: 3 8 4 7 1 6 2 5 [28]: 3 1 7 5 8 2 4 6 [29]: 4 6 8 2 7 1 3 5 [30]: 4 6 8 3 1 7 5 2[31]: 4 6 1 5 2 8 3 7 [32]: 4 7 1 8 5 2 6 3 [33]: 4 7 3 8 2 5 1 6 [34]: 4 7 5 2 6 1 3 8 [35]: 4 7 5 3 1 6 8 2 [36]: 4 8 1 3 6 2 7 5 [37]: 4 8 1 5 7 2 6 3 [38]: 4 8 5 3 1 7 2 6 [39]: 4 1 5 8 2 7 3 6 [40]: 4 1 5 8 6 3 7 2 [41]: 4 2 5 8 6 1 3 7 [42]: 4 2 7 3 6 8 1 5 [43]: 4 2 7 3 6 8 5 1 [44]: 4 2 7 5 1 8 6 3 [45]: 4 2 8 5 7 1 3 6 [46]: 4 2 8 6 1 3 5 7 [47]: 5 7 1 3 8 6 4 2 [48]: 5 7 1 4 2 8 6 3 [49]: 5 7 2 4 8 1 3 6 [50]: 5 7 2 6 3 1 4 8 [51]: 5 7 2 6 3 1 8 4 [52]: 5 7 4 1 3 8 6 2 [53]: 5 8 4 1 3 6 2 7 [54]: 5 8 4 1 7 2 6 3 [55]: 5 1 4 6 8 2 7 3 [56]: 5 1 8 4 2 7 3 6 [57]: 5 1 8 6 3 7 2 4 [58]: 5 2 4 6 8 3 1 7 [59]: 5 2 4 7 3 8 6 1 [60]: 5 2 6 1 7 4 8 3 [61]: 5 2 8 1 4 7 3 6 [62]: 5 3 8 4 7 1 6 2 [63]: 5 3 1 6 8 2 4 7 [64]: 5 3 1 7 2 8 6 4 [65]: 6 8 2 4 1 7 5 3 [66]: 6 1 5 2 8 3 7 4 [67]: 6 2 7 1 3 5 8 4 [68]: 6 2 7 1 4 8 5 3 [69]: 6 3 5 7 1 4 2 8 [70]: 6 3 5 8 1 4 2 7 [71]: 6 3 7 2 4 8 1 5 [72]: 6 3 7 2 8 5 1 4 [73]: 6 3 7 4 1 8 2 5 [74]: 6 3 1 7 5 8 2 4 [75]: 6 3 1 8 4 2 7 5 [76]: 6 3 1 8 5 2 4 7 [77]: 6 4 7 1 3 5 2 8 [78]: 6 4 7 1 8 2 5 3 [79]: 6 4 1 5 8 2 7 3 [80]: 6 4 2 8 5 7 1 3 [81]: 7 1 3 8 6 4 2 5 [82]: 7 2 4 1 8 5 3 6 [83]: 7 2 6 3 1 4 8 5 [84]: 7 3 8 2 5 1 6 4 [85]: 7 3 1 6 8 5 2 4 [86]: 7 4 2 5 8 1 3 6 [87]: 7 4 2 8 6 1 3 5 [88]: 7 5 3 1 6 8 2 4 [89]: 8 2 4 1 7 5 3 6 [90]: 8 2 5 3 1 7 4 6 [91]: 8 3 1 6 2 5 7 4 [92]: 8 4 1 3 6 2 7 5。
c++八皇后问题最简单算法
![c++八皇后问题最简单算法](https://img.taocdn.com/s3/m/ea1d0062ae45b307e87101f69e3143323968f5e8.png)
八皇后问题是一个经典的回溯算法问题。
下面是一个使用C语言实现的简单算法:c复制代码#include<stdio.h>#include<stdbool.h>#define N 8int col[N] = {0}; // 表示皇后所在的列int queens[N][N] = {0}; // 存储棋盘状态bool is_valid(int row, int col) {for (int i = 0; i < row; i++) {if (queens[i][col] || queens[i][col - (row - i)] || queens[i][col + (row -i)]) {return false;}}return true;}void backtrack(int row) {if (row == N) { // 找到了一组解for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {printf("%d ", queens[i][j]);}printf("\n");}return;}for (int col = 0; col < N; col++) {if (is_valid(row, col)) { // 如果当前位置是合法的,则放置皇后queens[row][col] = 1;col[row] = col; // 记录每行皇后所在的列backtrack(row + 1); // 继续放下一行的皇后queens[row][col] = 0; // 回溯,撤销当前位置的皇后}}}int main() {backtrack(0); // 从第0行开始放皇后return0;}在上面的代码中,我们使用一个一维数组col来记录每一行皇后所在的列。
在is_valid函数中,我们检查当前位置是否合法,即与前面的皇后不冲突。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
八皇后问题学
2012年 9 月 5 日
目录
一、选题
1.1背景知识 (2)
1.2设计目的与要求 (2)
二、算法设计
2.1问题分析 (3)
2.2算法设计 (3)
三、详细设计
3.1源程序清单 (4)
四、调试结果及分析
4.1调试结果 (6)
4.2调试分析 (7)
五、课程设计总结
5.1总结及体会 (7)
六、答辩
6.1答辩记录 (8)
6.2教师意见 (8)
一、选题及背景知识
1.1 背景知识
在国际象棋中,皇后是一个威力很大的棋子,她可以“横冲直撞”(在正负或垂直方向走任意步数),也可以“斜刺冲杀”(在正负45度方向走任意步数),所以在8*8的棋盘上要布互相不受攻击的皇后,最多只能布八个,共92种布法,再也不能有别的布法了——这就是著名的八皇后问题
在8*8的国际象棋棋盘上,放置八个皇后,使得这八个棋子不能互相被对方吃掉。
也就是说一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
1.2 设计要求
要求:·判断在国际象棋中,能否在空棋盘上摆放8个皇后,并使其中任意两个皇后不能在同一行,同一列或同一对角线上。
·编写完整的摆放八皇后问题的程序
·具体要求第一个皇后的起始位置由键盘输入
二、算法设计
2.1问题分析
设计——图形表示下图中,Q代表皇后
假设在第k列上找到合适的位置放置一个皇后,要求它与第1——k-1列上的皇后不同行、列、对角线;可以从图上找到规律:不同列时成立,皇后放在第k列上;讨论行时,第j个皇后的位置(a[j] ,j)要与(i,k)位置的皇后不同行;如果同在/斜线上,行列值之和相同;如果同在\斜线上,行列值之差相同;如果斜线不分方向则同一斜线上两皇后的行号之差的绝对值与列号之差的绝对值相同,可表示为(|a[j]-i|=|j-k|)。
2.2 算法设计
利用计算机运行速度快的特点,采用枚举法,逐一尝试各种摆放方式,来判断最终摆法。
其中判断是否同在对角线上用到了:行数差的绝对值与列数差的绝对值相等,
来简化问题的判断。
以a,b,c,d,e,f,g,h 的值表示皇后在第一,二,三,四,五,六,七,八行对应的列数就很好的解决了行列的问题。
我的想法:,只是要能根据输入的位置进行程序。
我使用了switch 选择结构语句,j 表示行数,k表示列数,当j为一时即皇后在第一行,然后再看a与k是否相等,当a不等于k时,则continue,跳出本次循环,知道a等于k时。
其中函数大致分为三大模块:
1、排列出一种八皇后排列方法
2、用swich判断是否有一个位置与输入的相同
3、若满足,输出皇后列数,即a,b,c,d,e,f,g,h.
三、详细设计和编码
#include <stdio.h>
#include <math.h>
#include<conio.h>
int main()
{
int a, b, c, d, e, f, g, h; //定义每行所放皇后位置的列数
int x, y; //定义输入皇后的行数及列数
printf("input position");
scanf("%d", &x);
scanf("%d", &y);
//开始确定能摆放八个皇后的摆法
for(a=1;a<=8;++a) //开始确定第一个皇后的列数
for(b=1;b<=8;++b) { //开始确定第二个皇后的列数
if(a==b) continue; //以此类推...
if(abs(b-a)==1) continue;
for(c=1;c<=8;++c) {
if(c==a||c==b) continue;
if(abs(c-a)==2||abs(c-b)==1) continue;
for(d=1;d<=8;++d) {
if(d==a||d==b||d==c) continue;
if(abs(d-a)==3||abs(d-b)==2||abs(d-c)==1) continue;
for(e=1;e<=8;++e) {
if(e==a||e==b||e==c||e==d) continue;
if(abs(e-a)==4||abs(e-b)==3||abs(e-c)==2||abs(e-d)==1) continue;
for(f=1;f<=8;++f){
if(f==a||f==b||f==c||f==d||f==e) continue;
if(abs(f-a)==5||abs(f-b)==4||abs(f-c)==3||abs(f-d)==2||abs(f-e)==1) continue; for(g=1;g<=8;++g) {
if(g==a||g==b||g==c||g==d||g==e||g==f) continue;
if(abs(g-a)==6||abs(g-b)==5||abs(g-c)==4||abs(g-d)==3||abs(g-e)==2||abs(g-f) ==1) continue;
for(h=1;h<=8;++h) {
if(h==a||h==b||h==c||h==d||h==e||h==f||h==g) continue;
if(abs(h-a)==7||abs(h-b)==6||abs(h-c)==5||abs(h-d)==4||abs(h-e)==3||abs(h-f) ==2||abs(h-g)==1) continue;
// 判断以上产生的结果是否满足所输入的皇后位置switch(x) { // 若不满足,从新尝试其他摆法。
若满足则输出八个皇case 1: // 后的位置
if(y!=a) continue;
break;
case 2:
if(y!=b) continue;
break;
case 3:
if(y!=c) continue;
break;
case 4:
if(y!=d) continue;
break;
case 5:
if(y!=e) continue;
break;
case 6:
if(y!=f) continue;
break;
case 7:
if(y!=g) continue;
break;
case 8:
if(y!=h) continue;
break;
}
printf("(1,%d) ",a); // 输出皇后位置的一种摆法
printf("(2,%d) ",b);
printf("(3,%d) ",c);
printf("(4,%d) ",d);
printf("(5,%d) ",e);
printf("(6,%d) ",f);
printf("(7,%d) ",g);
printf("(8,%d) ",h);
printf("\n");
getch(); // 依次输出各种摆法
}}}}}}}}
四、程序调试结果及分析
程序一步步修改完毕,但没有达到依次输出结果的要求,为此“请教”
了C++函数"conio.h",在原有基础上添加了几个语句实现了手动输出结果。
在编写程序过程中曾多次将括号写重复了,所以在编写时尽量使括号成对出现,这样就不会多了或者漏了。
以下是一次运行结果:
显然,当我输入1 3 是得到结果如下,即当第一皇后在第一行第三列时,其他皇后分别在2,3,4,5,6,7,8行的 3,7,5,8,2,4,6列。
或者2,3,4,5,6,7,8行的3,5,2,8,1,7,4,6列,或者。
五、课程设计总结
在整个过程中,我认识到了C语言功能丰富,表达能力强,使用灵活方便,应用面广,适合编写系统软件。
C语言不仅为计算机专业工作者所使用,对我们在校大学生也是一门必须掌握的技能。
因为在以后工作及其生活中,我们就极大可能会遇到一些问题需要用程序去解决。
我在这一周的学习中获益匪浅!学到了以前没注意的小节,让我更深的了解C程序,让我也发现了自己的不足。
我也会从这次程序设计中好好总结。
在一次一次的编程过程中,出现了许多的错误和纰漏,在对程序的一次一次改错过程中,我的分析与纠正错误的能力有了明显的提高。
而且我发现在编程时,要更注重算法的选择和使用,加入新的算法去尝试改变自己的一些编程思想,保持更新算法这才是关键。
六、答辩
6.1 答辩记录6.2教师意见。