数据结构课程设计用C++语言解决八皇后问题_第1页
数据结构课程设计用C++语言解决八皇后问题_第2页
数据结构课程设计用C++语言解决八皇后问题_第3页
数据结构课程设计用C++语言解决八皇后问题_第4页
数据结构课程设计用C++语言解决八皇后问题_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 用c+语言解决八皇后问题 1 引 言在程序设计中,可以用两种方法解决问题:一是传统的结构化程序设计方法,二是更先进的面向对象程序设计方法。在结构化程序设计中关键是如何将问题域中的行为(即操作)抽取出来,作为c+程序中的函数。由于多个函数均需要访问某些数据,这些数据常被设计为全局变量。而在面向对象程序设计中关键是如何将问题域中的实体(即日常所见的概念)抽取出来,作为c+程序中的类,而属性与行为作为类的两类要素通常是必不可少的,甚至还应考虑类必须满足的约束1。1.1课程设计目的深入理解数据结构的基本理论,掌握数据存储结构的设计方法,掌握基于数据结构的各种操作的实现方法,训练对基础知识和基本方法的

2、综合运用能力,增强对算法的理解能力,提高软件设计能力。在实践中培养独立分析问题和解决问题的作风和能力。熟练运用c+语言、基本数据结构和算法的基础知识,独立编制一个具有中等难度的、解决实际应用问题的应用程序2。1.2课程设计内容国际象棋中皇后威力很大,它可以象“车”一样沿直线上下或左右移动;也可以如同“象”那样沿着斜线移动。双方的皇后是不能在同一行或同一列或同一斜线上对持的。那么,在一张空白的国际象棋盘上最多可以放上几个皇后并且不让它们互相攻击呢?这个问题是伟大数学家高斯在十九世纪中期提出来的,并作了部分解答。高斯在棋盘上放下了八个互不攻击的皇后,他还认为可能有76种不同的放法,这就是有名的“八

3、皇后”问题。现在我们已经知道八皇后问题有92个解答。那么你能试着找出几种方法吗?如果你动手试试,就一定会发现开头几颗皇后很容易放置,越到后来就越困难。由于我们的记忆有限,很可能在某个位置放过子后来证明不行取消了,但是以后又重新放上子去试探,这样就会不断地走弯路,花费大量的精力。因此,必须找到一个简易有效、有条不紊的法则才行3。 2问题描述和分析2.1问题描述在一个的棋盘里放置个皇后,要求每个皇后两两之间不相冲(在每一横列竖列斜列只有一个皇后)。一个合适的解应是在每列、每行确实有一个皇后,且在一条对角线上最多只有一个皇后2.2分析问题分析:(1) 满足上述条件的八个皇后,必然是每行一个,每列一个

4、。(2)棋盘上任意一行、任意一列、任意一条斜线上都不能有两个皇后。如果我们把88的棋盘看成是一个平面直角坐标系,则八皇后问题就可以用数学语言来描述了,任意两个皇后在平面上的坐标应该同时满足以下三个条件:两个皇后不在同一行:两个皇后的横坐标不相等;两个皇后不在同一列:两个皇后的纵坐标不相等;两个皇后不在同一条斜线上:两个皇后的横坐标之差的绝对值不等于两个皇后的纵坐标之差的绝对值。依据“分而治之”的思想,先讨论4皇后的问题。也就是说在44的盘内放4个后。8皇后的问题实际上是4皇后问题的衍生。如图2.1所示。图2.1 模拟棋盘图首先清理棋盘,把所有的坐标值都归零,如图2.2所示。 图 2.2 棋盘坐

5、标清零然后放第一个q1到(1,1)的位置,。即q1.row=1,q1.col=1,如图2.3所示。图2.3 放入第一颗棋子q1会占据它所在的所有横,竖,斜的位置。调用seize(1,1)函数来实现这个功能。让q1所在的横竖斜线上所在的坐标都置1,如图2.4所示。图2.4 继续探索接着放q2。放q2的过程可以看作是在43的棋格里放q2-q4的过程。其中33的棋格中间斜线被q1占据,因此q2放在(2,3)的位置。即q2.row=2,q2.col=3。放完q2后,调用seize(2,3)函数来实现q2的占据坐标,如图2.5所示。 图2.5 划出下一颗棋子可能的区间接下来要放q3,可以看作是一个在42

6、的棋格里放q3、q4。但是我们看到第3行已经没有空位放q3了。因此回退到q2的时刻,把q2往后放,寻找第2个适合q2的位置。若没有位置可放,则退回到q1改变q1的位置,如图2.6所示。图2.6 放入第二颗棋子q2从(2,3)的位置出来后,可以放在(2,4)的位置。即q2.row=2,q2.col=4。如此q3便可放到(3,2)的位置,如图2.7所示。图2.7 继续探索但是如此一来,q3放在(3,2)的位置会占据q4(4,3)的位置使q4无法安放。所以应该回退到q1。使q1放在(1,2)的位置,如图2.8所示。 图2.8 无解 退回q1q2因为(2,1)(2,2)(2,3)都被q1占据,因此只能

7、放在(2,4)的位置,如图2.9所示。图2.9 得出一个解至此,我们已经得到4皇后的一个解,判断是否已解出的条件是q4是否被安放成功。此时q4被安置,得出一个解,因此应该输出4个q的位置调用函数print()输出此时的4个q的位置。输出以后程序还没有完,因为我们还没有把所有的棋盘都遍历完毕。q1只是到了(1,2)。要到(1,4)以后程序才算结束。所以我们应该把q1往后移动一位到(1,3)继续找解。q1在(1,3)的时候重复上边的过程可以得到q4的另一组解。我们可以看到,四皇后的两个解是相对的(对称)。实际上皇后问题的任何一个解都有另外一个解和它相对应。因此皇后问题的解一定是一个偶数。最后q4到

8、了(1,4)以后全部棋盘遍历完毕。输出所有的解。程序结束。我们可以设计一个函数queen(int i)来模拟4q的递归调用。另外需要一个seize(i,j)函数判断坐标(i,j)是否被占据。一个print()函数来打印解。因为整个函数调用是一个递归的过程,递归结束后一切解都被析构了,所以print()函数必须被安置在queen(int k)函数里。seize(i,j)函数作用是判断坐标(i,j)是否被占据,如占据则返回1,如没占据则返回0。我们往(3,2)中放q3。在判断是否占据的时候,需要考虑3中情况:1.列上是否被占据了。即图中的(2,2)(1,2)两点,注意,在这里只需要判断i(既3)以

9、上的坐标就行了,因为第3行以下不可能有q,我们还没有放。因此不用判断(4,2)这个点。(2,2)(1,2)两点的坐标用算法表示可以写成k=i-1 to 1;if(k,j)=q) retrun 1; return 02.左斜线上是否被占据了。即图中的(2,1)。算法可以写成:k=i-1 to 1if(k,j-i+k)=q) return1;return 03.右斜线上是否被占据了。即图中的(2,3)(1,4)。算法可以写成:k=i-1 to 1if(k,j+i-k)=q) return1;return 0后把三种情况进行逻辑或运算以后返回给主函数。换句话说就是行,左斜,右斜只要有一个有q存在的话

10、,就返回1给主函数,否则返回0。 3数据结构设计3.1数据结构设计考虑我们用q1-q4四个整型数组来表示4个q。qi的数值表示q所在的位置。比如q1=3表示q1放在(1,3)的位置。44的棋盘我们用一个整型变量size来表示。要改变棋盘的大小只需要改变size的数值即可。最主要的是queen(int i)函数的设计。queen(int i)函数负责主要的棋盘遍历,从第一个q放入到遍历结束。另外queen(int i)函数也是一个递归函数,当q8没有被放置时,不断的调用自己。直到q8成功放置,输出解。3.2流程图 图3.1流程图主程序比较简单,只需要调用一个queen(1)的函数把1传给函数中的

11、变量。queen函数负责解决解法问题。这是一个递归的过程,当放下第1个q后,接着自己调用自己放第2个q。直到4和q放完。如果放完后则输出组合。然后移动第1个q的位置继续进行。直到所有的棋盘都被遍历结束4。4算法设计4.1主要设计思想回溯的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。如迷宫问题:进入迷宫后,先随意选择一个前进方向,一步步向前试探前进,如果碰到死胡同,说明前进方向已无路可走,这时,首先看其它方向是否还有路可走,如果有路可走,则沿该方向再向前试探;如果已无路

12、可走,则返回一步,再看其它方向是否还有路可走;如果有路可走,则沿该方向再向前试探。按此原则不断搜索回溯再搜索,直到找到新的出路或从原路返回入口处无解为止5。4.2算法的伪码描述主程序较简单,只需要进行一些参数赋值,并执行queen函数即可。algorithm main ()1input size2queen(1)3returnend mainqueen函数:程序的核心部分,解皇后问题的全部过程由该函数完成。依据流程图写出算法。algorithm queen(val k)1 i=12 loop (isize)1break2else1q(k)=i2if(k=size)1print()3queen(

13、k+1)3end loop4returnend queenseize函数:函数作用是判断坐标(i,j)是否被占据,如占据则返回1,如没占据则返回0。algorithm seize(val i ,val j )1k=i-1;2loop (k=0)1if (qk=j|qk=j+i-k|qk=j-i+k)1return 12k=k-13end loop4return 0end seizeprint函数:函数作用是打印已经的出的一组解。在调用函数的时候,q1-q4里存的分别是四个q的纵坐标。用两个循环嵌套打印。algorithm printdigit()1i=02loop(isize)1print q

14、i3printcount+4i+5returnendprintdigit 以上是打印数据的一组解。每个数字分别代表相应的q的纵坐标。这样打印的优点是简单,快捷。但是没有图形输出,不方便用户查看。下边我们定义一个图形打印printgraphic函数algorithm printgraphic()1i=1;j=12loop(i=size)1printcount+“is:”2loop(j=size)1if(qi=j)1print“q”i2else print“”3end loop3end loop4returnend printgraphic这个函数会直接打印出一组解的图形表达形式。如像图的4q问题

15、解会如下打印:qqqq在打印时我们可以交替使用这两个函数。可以先用printdigit把所有的解都打出来,然后用printgraphic打印特定的用户选择的解。4.3运行环境本程序在windows xp系统vc+6.0环境下调试、运行4.4运行结果程序运行开始,进入提示界面,按任意键进入数据计算功能如图411图4.1按任意键进行 操作输出问题的各种解,如图4.2,图4.2 输出92种解5结束语 这次课程设计,主要是解决了八皇后问题,得出该问题的92种可能。该课题是一个十分有趣项目。通过这次设计我从中了解到无论是在上个世纪还是现在,软件开发所涉及的工作基本都没有变化,它们都起始于一个实际需要或某

16、个灵感,然后就是分析,设计,编码,调试,维护。这些任务以某种方式动态地结合起来就构成了软件开发的整个过程,这就是所谓的“软件开发周期”。但对于这些工作,具体怎样做,什么时候做,每个人都有自己的一套方式,甚至有的人有几套方式。数据结构是计算机专业很重要的一门课程,也是必须要熟练掌握的课程,这次的课程设计对我的数据结构知识进行了一次全面的综合训练,加深了对数据结构基本概念和基本知识的理解,巩固了课堂上学的知识,掌握了数据结构的一些基本方法,深刻理解了算法,锻炼了自己分析问题解决问题的能力。在本课程设计完成之际,最先要感谢的就是我的导师曾爱群老师。曾老师有着丰富的经验、对知识的追求孜孜不倦、精益求精

17、的治学态度、给我留下了深刻的印象。我很庆幸我在此次课程设计中选择曾老师做我的导师,能与曾老师这样的学识渊博,有实践经验的老师做课题,对我今后的学习工作将有很大益处。我深深的感受到自己在课程设计期间,在曾老师的指导下受益匪浅。 在本次课程设计过程中,曾老师为我提出了很多建议和意见,在这个学期中,我们随时都能与他取得联系询问相关问题,我的这次设计顺利完成离不开曾老师的帮助,曾老师为我的论文的顺利完成提供了极大的支持。在做课题的这段时间里,我不仅跟曾老师学会了怎样做学问,更从曾老师身上学到了许多做人的道理。曾老师严于律己、宽以待人的崇高品质更将是我一生的榜样。无论在学习上,还是在生活中,我从曾老师身

18、上学到了很多东西,这些将成为我一笔宝贵的财富。在此,我衷心的感谢曾老师为我所做的一切,感谢曾老师对我的关心、指导和教诲。参考文献1 richard f. gilberg, behrouz a. forouzan. data structure. brooks/cole, thomson asia pte ltd, usa, 2000.2 严蔚敏, 吴伟民. 数据结构(第二版). 北京:清华大学出版社, 1992.3 朱晓冬, 段延娥. 数据结构web动画算法. 软件评论, 2008,1:1-5498/computer_web/syllabus/data_stru

19、cture/course%20home,%20summer%202003.htm5王红梅,胡明,王涛 数据结构c+版 北京清华大学出版社,2005.7附录1 源程序清单#include stdio.hint a8,b24,c24,d24;int i, k,g1=0,g2=0;void print1() g1+;printf(t第%2d种情况: ,g1); for (k=1;k9;k+) printf(%4d,ak);/ getch(); printf(n);void print2() int t,n;g2+; printf(t第%2d种情况: nt,g2); for (k=1;k9;k+) n

20、=ak; for(t=1;tn;t+) printf(0 ); printf(1 ); t+; for(t;t9;t+) printf(0 ); printf(nt);printf(n);getch();void try1(int i) int j; for (j=1;j9;j+) /*每个皇后都有8种可能位置*/ if (bj=0) &(ci+j=0)& (di-j=0)/*判断位置是否冲突*/ ai=j; /*摆放皇后*/ bj=1; /*宣布占领第j行*/ ci+j=1; /*占领两个对角线*/ di-j=1; if (i8) try1(i+1); /*8个皇后没有摆完,递归摆放下一皇后*/ else print1(); /*完成任务,打印结果*/ bj=0; /*回溯*/ ci+j=0; di-j=0; void try2(int i) int j; for (j=1;j9;j+) /*每个皇后都有8种可能位置*/ if (bj=0) &(ci+j=0)& (di-j

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论