


下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、数据结构试验迷宫问题(一)基本问题1问题描述这是心理学中的一个经典问题。心理学家把一只老鼠从一个无顶盖的大盒子 的入口处放入,让老鼠自行找到出口出来。迷宫中设置很多障碍阻止老鼠前行, 迷宫唯一的出口处放有一块奶酪,吸引老鼠找到出口。简而言之,迷宫问题是解决从布置了许多障碍的通道中寻找出路的问题。本题设置的迷宫如图1所示。入口迷宫四周设为墙;无填充处,为可通处。设每个点有四个可通方向,分别为东、南、西、北(为了清晰,以下称"上下左右”)。左上角为入口。右下角为出口。迷宫有一个入口,一个出口。设计程序求解迷宫的一条通路。2.数据结构设计以一个n的数组mg表示迷宫,每个元素表示一个方块状态
2、,数组元素0和1分别表示迷宫中的通路和障碍。迷宫四周为墙,对应的迷宫数组的边界元素 均为1。根据题目中的数据,设置一个数组mg如下int mgM+2N+2=1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1;在算法中用到的栈采用顺序存储结构,将栈定义为Struct int i; / 当前方块的行号int j; / 当前方块的列号int di; /di是下一个相邻的可走的方位号stMaxSize; 定义栈int top=-1 / 初始化栈3设计运算算法要寻找
3、一条通过迷宫的路径,就必须进行试探性搜索,只要有路可走就前进 一步,无路可进,换一个方向进行尝试;当所有方向均不可走时,则沿原路退回 一步(称为回溯),重新选择未走过可走的路,如此继续,直至到达出口或返回 入口(没有通路)。在探索前进路径时,需要将搜索的踪迹记录下来,以便走不 通时,可沿原路返回到前一个点换一个方向再进行新的探索。后退的尝试路径与 前进路径正好相反,因此可以借用一个栈来记录前进路径。方向:每一个可通点有4个可尝试的方向,向不同的方向前进时,目的地的 坐标不同。预先把4个方向上的位移存在一个数组中。如把上、右、下、左(即 顺时针方向)依次编号为0、1、2、3.其增量数组move4
4、如图3所示。move4 x y图2数组move4力位3<,j-1)方位1(J. J+l>方位示意图如下:(i+lP J)方位2图3.方位图通路:通路上的每一个点有3个属性:一个横坐标属性i、一个列坐标属性 j和一个方向属性di,表示其下一点的位置。如果约定尝试的顺序为上、右、下、 左(即顺时针方向),则每尝试一个方向不通时,di值增1,当d增至4时,表 示此位置一定不是通路上的点,从栈中去除。在找到出口时,栈中保存的就是一 条迷宫通路。(1)下面介绍求解迷宫(xi,yj )到终点(xe,ye )的路径的函数:先将入口进 栈(其初始位置设置为一1),在栈不空时循环一一取栈顶方块(不退
5、栈)若该 方块为出口,输出所有的方块即为路径,其代码和相应解释如下:数据结构试验迷宫问题int mgpath(int xi,int yi,int xe,int ye)/求解路径为:(xi,yi)->(xe,ye)struct/ 当前方块的行号/ 当前方块的列号/di 是下一可走方位的方位号/ 定义栈/ 初始化栈指针/ 初始方块进栈int i;int j;int di; stMaxSize;int top=-1;int i,j,k,di,find;/ 栈不空时循环top+; sttop.i=xi;sttop.j=yi; sttop.di=-1;mg11=-1; while (top>
6、-1) i=sttop.i;j=sttop.j;di=sttop.di; /取栈顶方块if (i=xe && j=ye)/ 找到了出口 , 输出路径 printf(" 迷宫路径如下 :n");for (k=0;k<=top;k+)printf("t(%d,%d)",stk.i,stk.j);if (k+1)%5=0)/ 每输出每 5 个方块后换一行printf("n");printf("n");return(1); / 找到一条路径后返回 1 否则,找下一个可走的相邻方块若不存在这样的路径,
7、说明当前的路径不可能 走通,也就是恢复当前方块为 0后退栈。 若存在这样的方块, 则其方位保存在栈 顶元素中,并将这个可走的相邻方块进栈(其初始位置设置为-1)求迷宫回溯过程如图 4 所示兰前方纵(b j)液一孑方块役找至U址擁宜蜕其他路吐从前一个方块找到相邻可走方块之后,再从当前方块找在、相邻可走方块,若没有这样的方快,说明当前方块不可能是从入口路径到出口路径的一个方块,则从当前方块回溯到前一个方块,继续从前一个方块找可走的方块。为了保证试探的可走的相邻方块不是已走路径上的方块,如(i,j )已经进栈,在试探(i+1,j)的下一方块时,又试探道(i, j),这样会很悲剧的引起死循环,为此,在
8、一个方块进栈后,将对应的 mg数组元素的值改为-1 (变为不可走的相邻方块),当退栈时(表示该方块没有相邻的可走方块),将其值恢复0,其算法代码和相应的解释如下:fin d=0;while (di<4 && fin d=0)/ 找下一个可走方块di+;switch(di)case 0:i=sttop.i-1;j=sttop.j;break;case 1:i=sttop.i;j=sttop.j+1;break;case 2:i=sttop.i+1;j=sttop.j;break;case 3:i=sttop.i,j=sttop.j-1;break;if (mgij=0) f
9、in d=1;找到下一个可走相邻方块if (fin d=1)找到了下一个可走方块sttop.di=di;修改原栈顶元素的 di值top+;/下一个可走方块进栈sttop.i=i;sttop.j=j;sttop.di=-1;mgij=-1;避免重复走到该方块 else/没有路径可走,则退栈mgsttop.isttop.j=0;让该位置变为其他路径可走方块top-;将该方块退栈return(O); /表示没有可走路径,返回0(2)求解主程序建立主函数调用上面的算法,将mg和st栈指针定义为全局变量void mai n()mgpath(1,1,M,N);3界面设计设计很简单的界面,输出路径4运行结果
10、图5。基本运行结果(二) 8个方向的问题1.设计思想(1) 设置一个迷宫节点的数据结构。(2) 建立迷宫图形。(3)对迷宫进行处理找出一条从入口点到出口点的路径。(4)输出该路径。(5)打印通路迷宫图。图6功能结构图当迷宫采用二维数组表示时,老鼠在迷宫任一时刻的位置可由数组的行列序 号i,j来表示。而从i,j位置出发可能进行的方向见下图 7.如果i,j周围的位 置均为0值,则老鼠可以选择这8个位置中的任一个作为它的下一位置。将这8个方向分别记作:E (东八SE (东南)、S (南)SW (西南)W (西八NW (西 北)、N (北)和NE (东北)。但是并非每一个位置都有8个相邻位置。如果i,
11、j 位于边界上,即i=1,或i=m,或j=1,或j=n,则相邻位置可能是3个或5个为 了避免检查边界条件,将数组四周围用值为1的边框包围起来,这样二维数组maze应该声明为mazem+2,n+2在迷宫行进时,可能有多个行进方向可选,我 们可以规定方向搜索的次序是从东(E)沿顺时针方向进行。为了简化问题,规 定i,j的下一步位置的坐标是x,y,并将这8个方位伤的x和y坐标的增量预 先放在一个结构数组 move8中(见图8)。该数组的每个分量有两个域 dx和dy。例如 要向东走,只要在j值上加上dy,就可以得到下一步位置的x,y值为i+dy。于是搜索方向的变化只要令方向值dir从0增至7,便可以从
12、move数组中得到从i,j点出发搜索到的每一个相邻点x,y。x=i+movedir.dxy=j+movedir.dyy/1r图7方向位移图22 1Ip |1 丁21+? 松2-I*3-2dx dy图8向量差图为了防止重走原路,我们规定对已经走过的位置,将原值为 0改为-1,这既 可以区别该位置是否已经走到过, 又可以与边界值1相区别。当整个搜索过程结 束后可以将所有的-1改回到0,从而恢复迷宫原样。这样计算机走迷宫的方法是:采取一步一步试探的方法。每一步都从(E)开始,按顺时针对8个方向进行探测,若某个方位上的mazex,y=0,表示可以 通行,则走一步;若mazex,y=1,表示此方向不可通
13、行须换方向再试。直至8个方向都试过,mazex,y均为1,说明此步已无路可走,需退回一步,在上一 步的下一个方向重新开始探测。为此需要设置一个栈,用来记录所走过的位置和 方向(i,j,dir)。当退回一步时,就从栈中退出一个元素,以便在上一个位置的下一个方向上 探测,如又找到一个行进方向,则把当前位置和新的方向重新进栈,并走到新的位置。如果探测到x=m,y=n,则已经到达迷宫的出口,可以停止检测,输出存 在栈中的路径;若在某一位置的8个方向上都堵塞,则退回一步,继续探测,如果已经退到迷宫的入口(栈中无元素) ,则表示此迷宫无路径可通行。2 系统算法(伪代码描述) :(1)建立迷宫节点的结构类型
14、 stack。(2) 入迷宫图形 0 表示可以通 1 表示不可以通。 用二维数组 mazem+2n+2 进行存储。数组四周用1表示墙壁,其中入口点(1,1)与出口点(m, n)固定。(3) 函数path()对迷宫进行处理,从入口开始: While(!(s->top=-1)&&(dir>=7)|(x=M)&&(y=N)&&(mazexy=-1) For(扫描八个可以走的方向)If(找到一个可以走的方向)进入栈 标志在当前点可以找到一个可以走的方向 避免重复选择 mazexy=-1 不再对当前节点扫描If(八个方向已经被全部扫描过,无可以
15、通的路)标志当前节点没有往前的路 后退一个节点搜索 If(找到了目的地)输出路径退出循环未找到路径(4) 输出从入口点到出口点的一条路径。(5) 输出标有通路的迷宫图。3算法流程图:图9算法流程图4.程序代码:#define M2 12 /*M2*N2 为实际使用迷宫数组的大小 */ #define N2 11#define maxlen M2 / 栈长度#include <stdio.h> #include<iostream.h> #include <malloc.h>int M=M2-2,N=N2-2;/M*N 迷宫的大小typedef struct /
16、 定义栈元素的类型int x,y,dir;elemtype;typedef struct / 定义顺序栈elemtype stack maxlen;int top;sqstktp;movestruct moved /定义方向位移数组的元素类型对于存储坐标增量的方向位移数组 int dx,dy; /void inimaze(int mazeN2)/ 初始化迷宫int i,j,num;for(i=0,j=0;i<=M+1;i+)/ 设置迷宫边界 mazeij=1;for(i=0,j=0;j<=N+1;j+) mazeij=1;for(i=M+1,j=0;j<=N+1;j+)maz
17、eij=1;cout<<" 原始迷宫为: "<<endl;for(i=1;i<=M;i+)for (j=1;j<=N;j+) num=(800*(i+j)+1500) % 327;/ 根据 MN 的值产生迷宫 if (num<150)&&(i!=M|j!=N)mazeij=1;else mazeij=0;cout<<mazeij<<" "/ 显示迷宫 cout<<endl; cout<<endl;/inimaze / void inimove(str
18、uct moved move)/ 初始化方向位移数组northeast/ 依次为 East, Southeast, south, southwest, west, northwest , north , move0.dx=0;move0.dy=1;move1.dx=1;move1.dy=1;move2.dx=1;move2.dy=0; move3.dx=1;move3.dy=-1;move4.dx=0;move4.dy=-1; move5.dx=-1;move5.dy-=1;move6.dx=-1;move6.dy=0;move7.dx=-1;move7.dy=1;/void inistack
19、(sqstktp *s) /* 初始化栈 */s->top=-1; /*inistack*/int push(sqstktp*s,elemtype x) if(s->top=maxlen-1) return(false);elses->stack+s->top=x;/* 栈不满,执行入栈操作 */ return(true);/*push*/elemtype pop(sqstktp *s)/* 栈顶元素出栈 */elemtype elem;if(s->top<0)/ 如果栈空,返回空值elem.x=NULL;elem.y=NULL;elem.dir=NULL;
20、 return(elem);elses->top-;/栈不空,返回栈顶元素return(s->stacks->top+1); /pop/void path(int mazeN2,struct moved move,sqstktp *s)/寻找迷宫中的一条通路int i,j,dir,x,y,f;elemtype elem;i=1;j=1;dir=0;maze11=-1; / 设11 为入口处do x=i+movedir.dx;/ 球下一步可行的到达点的坐标 y=j+movedir.dy;if(mazexy=0)elem.x=i;elem.y=j;elem.dir=dir;f=p
21、ush(s,elem);/ 如果可行将数据入栈 if(f=false)/ 如果返回假,说明栈容量不足 cout<<" 栈长不足 "i=x;j=y;dir=0;mazexy=-1;elseif (dir < 7) dir+;else elem=pop(s); /8 个方向都不行,回退 if(elem.x!=NULL)i=elem.x;j=elem.y; dir=elem.dir+1; while(!(s->top=-1)&&(dir>=7)|(x=M)&&(y=N)&&(mazexy=-1);/ 循
22、环if(s->top=-1)/ 若是入口,则无通路cout<<" 此迷宫不通 "elseelem.x=x; elem.y=y; elem.dir=dir;/ 将出口坐标入栈 f=push(s,elem);cout<<" 迷宫通路是: "<<endl;i=0;while (i <= s->top)cout<<"("<<s->stacki.x<<","<<s->stacki.y<<")
23、"/ 显示迷宫通路 if(i!=s->top)cout<<"->"if(i+1)%4=0)cout<<endl;i+;/void draw(int mazeN2,sqstktp *s)/在迷宫中绘制出通路cout<<" 逃逸路线为: "<<endl;int i,j;elemtype elem;for(i=1;i<=M;i+)/将迷宫中全部的 -1 值回复为 0 值 for(j=1;j<=N;j+)if(mazeij=-1) mazeij=0;while(s->top&
24、gt;-1)/ 根据栈中元素的坐标, 将通路的各个点的值改为 8elem=pop(s);i=elem.x;j=elem.y; mazeij=8; for(i=1;i<=M;i+)for(j=1;j<=N;j+)printf("%3d",mazeij);/ 显示已标记通路的迷宫cout<<endl;void main()/ 寻找迷宫通路程序sqstktp *s;int mazeM2N2;struct moved move8;数据结构试验一一迷宫问题/初始化迷宫数组/初始化栈/初始化方向位移数组/寻找迷宫通路/绘制作出通路标记的迷宫ini maze(ma
25、ze);s=(sqstktp *)malloc(sizeof(sqstktp); in istack(s);inimo ve(move); path(maze,move,s); cout<<e ndl;draw(maze,s);5.运行结果新建文件夹 C2)DebugCppB右向.exe*|01 « 1r 1 n n 1191010 0 18P 101i a i 00 10 00 0 10 110 1010 L 011 U U 1w 1 w 100 0 10X 0 L 00迂百通路是.<1 ” 1 >一XI ”2一一C23一一一一C4.S>>C5.
26、6>>CS.?>>C6.8>>C7,9>e>>C9,9>>C10,9>谨逸路线为:U H 1M 1 k) L b 1。丄E丄巧丄0101_ 0 1a ±0±0 a0 101 8 ± » 0 11_ 0 1a ±» s ±0n 101 n p i ft 1191301018910a i 0 i s 11 a a10 10 18a a i01 B 108JKi'ess: any Jc吕屮 ca continuie仝标增童旳万冋位移敢爼耐斥(三)求所有
27、通路和最短路径的算法#i nclude <stdio.h>#defi ne M 5#defi ne N 7#defi ne MaxSize 100 int mgM+1N+1= 1,1,1,1,1,1,1,1,1,0,0,1,000,1,1,1,000,1,1,1,1,0,0,1,0,0,0,1,1源代码(用原题的数据)/*行数*/*列数*/*栈最多元素个数*/*一个迷宫,其四周要加上均为1的外框*/*栈指针 */* 路径数计数 */* 最短路径长度 */* 路径为 :(1,1)->(M-2,N-2)*/*进栈 */while (top>-1)/* 栈不空时循环 */1,
28、0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 ;structint i;int j;int di; StackMaxSize,PathMaxSize; /* 定义栈和存放最短路径的数组 */ int top=-1;int count=1;int minlen=MaxSize;void mgpath()int i,j,di,find,k; top+; Stacktop.i=1; Stacktop.j=1;Stacktop.di=-1;mg11=-1; /* 初始结点进栈 */i=Stacktop.i;j=Stacktop.j;di=Stacktop.di;if (i=M-2 &am
29、p;& j=N-2) /* 找到了出口 ,输出路径 */printf("%4d: ",count+);for (k=0;k<=top;k+) printf("(%d,%d) ",Stackk.i,Stackk.j);if (k+1)%5=0) printf("nt");/*输出时每 5 个结点换一行 */* 比较找最短路径 */* 让该位置变为其他路径可走结点 */ printf("n");if (top+1<minlen)for (k=0;k<=top;k+) Pathk=Stackk;
30、minlen=top+1;mgStacktop.iStacktop.j=0;top-;i=Stacktop.i;j=Stacktop.j;di=Stacktop.di;find=0;while (di<4 && find=0) /* 找下一个可走结点 */ di+;switch(di)case 0:i=Stacktop.i-1;j=Stacktop.j;break;case 1:i=Stacktop.i;j=Stacktop.j+1;break;case 2:i=Stacktop.i+1;j=Stacktop.j;break;case 3:i=Stacktop.i,j=S
31、tacktop.j-1;break;if (mgij=0) find=1;if (find=1)/* 找到了下一个可走结点 */ Stacktop.di=di;/* 修改原栈顶元素的 di 值 */top+;Stacktop.i=i;Stacktop.j=j;Stacktop.di=-1;/* 下一个可走结点进栈 */ mgij=-1; /* 避免重复走到该结点 */else /* 没有路径可走 ,则退栈 */mgStacktop.iStacktop.j=0;/* 让该位置变为其他路径可走结点 */top-;printf(" 最短路径如下 :n");printf("
32、; 长度 : %dn",minlen);printf(" 路径 : ");for (k=0;k<minlen;k+)printf("(%d,%d) ",Pathk.i,Pathk.j);if (k+1)%5=0) printf("nt");/*输出时每 5 个结点换一行 */printf("n");void main()printf(" 迷宫所有路径如下 :n");mgpath();2 求解结果数据结构试验一一迷宫问题6实验收获及思考这次试验总体来说还是比较简单的,因为几个思考问题都是在基本问题的源代 码上进行改进和补充。有了第一次数据结构编程和测试的经验,这次试验减少了 很多困难,相对来说容易多了。附录基本问题换代码(思考问题源代码在上文中已经全部给出)#defi ne M 4#defi ne N 6#defi ne MaxSize 100#i nclude <stdio.h>int mgM+2N+2=1,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 互联网自媒体账号买卖及过户安全保障合同
- 石油勘探区块合作开发投资协议
- 电商平台绿色能源商品销售与推广服务协议
- 夫妻情感挽救忠诚协议婚姻修复最后机会条款
- 生态农业土壤改良及有机肥料施用技术合作协议
- 2025年广东省茂名市高考地理一模试卷
- DB42-T 1986-2023 长江干线湖北段船舶航行气象风险预警等级
- 汽车发动机构造与拆装 课件 任务12 散热器的认识与拆装
- 研修学习心得体会模版
- 2023年人教版四年级语文上册四单元测试卷及答案二
- 深圳市人才集团笔试题库
- 校园广播设备维保合同
- 反诈宣传课件小学生版
- 2024年全国职业院校技能大赛高职组(环境检测与监测赛项)考试题库(含答案)
- 舞蹈技巧培训课件
- 2025年形势与政策-加快建设社会主义文化强国+第二讲中国经济行稳致远
- 汽车维修服务客户满意度提升流程
- 2024人教版七年级下册生物第三单元 植物的生活 单元测试卷(含答案)
- 气象防灾减灾知识科普
- 中国慢性冠脉综合征患者诊断及管理指南2024版解读
- 广西田林八渡金矿 资源储量核实报告
评论
0/150
提交评论