ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:21.86KB ,
资源ID:26818288      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/26818288.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(迷宫求解问题资料.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

迷宫求解问题资料.docx

1、迷宫求解问题资料迷宫求解问题 摘要:用矩阵表示迷宫,将矩阵表示的迷宫转换成无向图,用邻接表存储。对无向图从入口结点开始广度优先搜索,用一个一维数组存储各个结点的前驱结点的编号,通过出口结点Vn找到其前驱结点Vn-1,再通过Vn-1找到Vn-2,依次类推直到找到出口结点。关键字:矩阵迷宫求解 一、需求分析 1.程序题目:迷宫求解问题。迷宫是一个如下所示的m行n列的0-1矩阵,0表示无障碍,1表示有障碍。设入口为(1,1),出口为(m,n),每次移动只能从一个无障碍的单元移到周围8个方向的任意一个无障碍的单元,编写程序给出一条通过迷宫的路径或者报告一个“无法通过”的信息。入口-(0,0,0,1,0

2、,0,0,1,0,0,0,1,0,0,1)(0,1,0,0,0,1,0,1,0,0,0,1,1,1,1)(0,1,1,1,1,1,0,1,0,0,1,1,1,0,1)(1,1,0,0,0,1,1,0,1,1,0,0,1,0,1)(1,0,0,1,0,1,1,1,1,0,1,0,1,0,1)(1,0,1,0,0,1,0,1,0,1,0,1,0,1,0)(1,0,1,1,1,1,1,0,0,1,1,1,1,0,0)(1,1,1,0,1,1,1,1,0,1,0,1,0,1,0)(1,0,1,0,1,0,1,1,1,0,1,0,0,0,1)(0,1,0,1,0,1,0,0,0,1,1,0,0,1,0)

3、-出口2程序说明及任务:迷宫问题要求寻找一条从入口到出口的路径。路径是由一组位置构成的,每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的东、南、西或北的邻居,如图C。计算机走迷宫的方法是,采取一步一步试探的方法。每一步都从东开始,按顺时针对8个方向进行试探,若某方向上maze(x,y)=0,表示可以通行,则走一步;若maze(x,y)=1,表示不可以通行,须换方向再试,直到8个方向都试过;若maze(x,y)均为1,说明此步已无路可走,需退回一步,在上一步的下一个方向重新开始探测。为此,需设置一个栈,用于记录所走过的位置和方向(i,j,dir)。当退回一步时,从栈中退出一个元素,

4、以便在上一个位置的下一个方向上探测,如又找到一个行进方向,则把当前位置和方向重新进栈,并走到新的位置。 若探测到位置(m,n),则已经到达迷宫的出口,可以停止探测,输出存在栈中的路径;如果在某一位置的8个方向上堵塞,则退回一步,继续探测;如果已退到迷宫的入口(栈中无元素),则表示此迷宫无路径可走。 二、概要设计 主要思想:1. 用矩阵表示的迷宫;2. 将矩阵表示的迷宫转换成无向图,用邻接表存储;3. 对无向图从入口结点开始广度优先搜索;4. 用一个一维数组存储各个结点的前驱结点的编号;5. 通过出口结点Vn找到其前驱结点Vn-1,再通过Vn-1找到Vn-2;6. 依次类推直到找到出口结点。 基

5、本设计算法:1. 设置数组mazeMAXMAX来模拟迷宫,2. maze ij=0表示该方格所在的位置可通行, Aij=1则表明该位置不能通行;3. 定义无向图G,迷宫的规格(行、列)存放在G.rownum、G.colnum中,其结点数同迷宫(数组maze MAXMAX)的方格个数。4. 每一个结点的邻接结点为其相邻(从点在数组maze 中所处的位置的角度)的八个点中值为0的点,按结点的顺序依次找出每一个点的邻接点,此即完成迷宫图的数组表示转化为无向图表示,G用邻接表存储;5. 采用图的广度优先遍历的方法,从入口结点开始遍历,直到碰到出口结点为止。并设置record数组来记录结点i在广度优先遍

6、历过程中的前驱结点的编号recordi;6. 这样(recordi,i)表示存在从结点recordi到i的边,这样就可以从出口顶点在图中的编号回溯出口顶点,如此,一条从入口到出口的最短路径就找到了。在定义record数组是将所有初始值设为-1,只是为了判断是否存在从入口到出口的路径, 因为如果出口结点i的recordi值为-1则表明遍历过程没有找到出口,也就是说此迷宫无解.7. 反之recordi!= -1,则此迷宫一定是有解的,因为只有遍历过程中找到了出口I,才会改变recordi的值,而这个改变后的值是不可能为-1的;8. 输出从入口到出口的路径,用回溯法,只需将图中结点的编号换算成数组m

7、aze的坐标即可。 三、详细设计 1. 基本过程的算法:设定a00为入口位置;do若当前位置可通,则将当前位置插入栈顶;若该位置是出口位置,则结束;否则切换当前位置的东邻方块为新的当前位置;否则,若栈不空且栈顶位置尚有其他方向未经探索,则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;若栈不空但栈顶位置的四周均不可通,则删栈顶位置;若栈不空,则重新测试新的栈顶位置,直到找到一个可通的相邻块或出栈至栈空;while(栈不空);#include . 函数的调用关系图迷宫存储从A00开始,包括记录路径的数组record也是从0下标开始纪录的,为了使输入和输出的坐标符合习惯,只在输入输出

8、时作了一些改变。 迷宫主要部分转换图示矩阵转化成图的邻接表存储:i(G.vexsi.data,G.vexsi.first)(adjno,next)1 (0,first)(11,NULL)2 (1,NULL)3 (1,NULL)11(0,first)(21,next)(1,NULL)59(0,first)(60,next)(49,NULL)60(0,first)(59,NULL)以入口结点作广度优先遍历的起始结点,知道找到出口结点结束遍历,并用recordi记录遍历的结点i的前驱结点recordi,然后用回溯法输出路径(路径换算成坐标形式)即可。 3.抽象数据类型定义描述 ADT T isDat

9、a 当前位置的行坐标、当前位置的列坐标、走到下一位置的方向end ADT T ADT Linknode isData 数据域、指针域Operation Linknode /构造函数 用于构造结点end ADT LinkNode ADT Stack isData 栈顶指针OperationStack /构造函数输入:无初始化栈:置空栈 stack /析构函数 Push 输入:要进栈的项e 前置条件:无 动作:把e压入栈顶 输出:无 后置条件:栈顶增加了一个新结点,栈顶指针指向新结点 Pop 输入:无 前置条件:栈非空 动作:弹出栈顶元素 输出:返回栈顶元素的值 后置条件:删除栈顶元素 GetPo

10、p 动作:返回栈顶元素的值 Clear 动作:清空栈 empty 动作: 检查栈顶指示是否等于NULL 输出:栈空时返回1,否则返回0end ADT Stack 四、调试分析 1)程序将用到的函数及参数:1. 迷宫输入: adjlist input (int maze MAX);2. 迷宫图的图结构(邻接表存储)化: adjlist convert (int maze MAX,adjlist G);3. 对图的广度优先遍历: void travgraph(adjlist G,int record,int entry,int exit);4. 迷宫的解的输出: void output (adjl

11、ist G,int record,int entry,int exit)。 2)算法分析和改进在程序的设计中,总的调试比较顺利。在找出一些小问题顺利编译成功以后,在测试结果的时候发现程序运行的结果错误。经过仔细的检查,发现程序中8个if语句中的算法出现错误。导致运行时搜索的方向发生错误。在if语句中的”i-1G.colnum&j+1=0&j+1G.colnum”后,错误解除。经过测试结果,结果正确。 虽然程序能够编译成功,但是还有2个警告项存在.winTC提示警告: success.c 126 :不可移动的指针(地址常数)转换在travgraph 函数中。 success.c 132 :不可移

12、动的指针(地址常数)转换在travgraph 函数中。 经过改进,问题成功解决。警告消失。对于不能显示汉语的TC,最后将中文转换为英文,唯一不足的是(*,*) 在显示的时候是乱码。未能几时改进。 3)体会:要能很好的掌握编程,仅仅通过几个简单的程序的编写是无法达成的,更需要大量 积累和深入才有可能。就从这个迷宫的问题来说,在迷宫图向图结构的转化时,对图可用广度优先搜索的算法来解决两点间路径问题。在程序的编写中也不能一味得向已有的程序进行模仿,而要自己去摸索,去寻求最好的解决方式,只有带着问题去反复进行实践,才能更熟练的掌握和运用,当然,对现有的程序也要多去接触,因为有些程序是我们无法在短时间内

13、想出来的。最重要的一点就是要持之以恒,要经常性的复习原来所接触的程序,这样才能保证我们有足够的经验去面对程序问题。 五、测试结果: 1.运行出现 “Please input the length of the maze”字样,“rownum”表示输入”行数” “colnum”表示输入”列数”。2.然后会出现 “Input the 1 row” 这时输入数组的第一行,后面的依次类推。3.数组输入完毕后,会出现” Inputting the maze entrance sits the mark(*,*)” 即输入起点坐标。 然后会出现”Inputting the maze exports to

14、sit the mark(*,*)”要求输入出口坐标。4.点击回车运行 所求的路径即会显示出来。 所示输入迷宫大小:行数(=15):10 列数(=15):150表示可通行,1表示不能通过。输入第1行:1 000100010001001输入第2行:2 010001010001111输入第3行:3 011111010011101输入第4行:4 110001101100101输入第5行:5 100101111010101输入第6行:6 101001010101010输入第7行:7 101111100111100输入第8行:8 111011110101010输入第9行:9 10101011101000

15、1输入第10行:10 010101000110010输入入口坐标(*,*):1,1输入出口坐标(*,*):10,15 附录 1.存储结构:邻接表存储存储2.基本过程的算法: (1). 栈初始化; (2). 将入口点坐标及到达该点的方向(设为-1)入栈; (3). while(栈不空时) 栈顶元素元素(x,y,d)出栈; 求出下一个要试探的方向d+; while (还有剩余试探方向时) if(d方向可走) 则 (x,y,d)入栈; 求新点坐标(i,j); 将新点(i,j)切换为当前点(x,y); if (x,y)= = (n,n)结束;else d=0; else d+; 3.源程序: #inc

16、lude #define MAX 15#define NULL 0 typedef struct listnodeint adjno; struct listnode *next;listnode; typedef structint data; listnode *first;headnode; typedef structheadnode vexsMAX*MAX; int vexnum; int rownum; int colnum;adjlist; adjlist G; /*输入迷宫,0为可通行,1为不可通行,用二维矩阵表示*/ adjlist input (int mazeMAX,ad

17、jlist G)int i,j; int rownum,colnum; printf(Please input the length of the maze:n); printf(rownum=); scanf(%d,&G.rownum); printf(colnum=); scanf(%d,&G.colnum); for(i=0;iG.rownum;i+) printf(Input the %d row:%d ,i+1,i+1); for(j=0;jG.colnum;j+) scanf(%d,&mazeij); return(G); /*二维数组向无向图的转化*/adjlist change

18、 (int mazeMAX,adjlist G)int i,j; listnode *p; G.vexnum=G.rownum*G.colnum; for(i=0;iG.vexnum;i+) /*图中结点的初始化*/ G.vexsi.data=mazei/G.colnumi%G.colnum; G.vexsi.first=NULL; for(i=0;iG.rownum;i+) /*将无向边用指针表示出来*/ for(j=0;j=0&mazei-1j=0) p=(listnode *)malloc(sizeof(listnode); p-adjno=(i-1)*G.colnum+j; p-nex

19、t=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; if(i+1adjno=(i+1)*G.colnum+j; p-next=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; if(j-1=0&mazeij-1=0) p=(listnode *)malloc(sizeof(listnode); p-adjno=i*G.colnum+j-1; p-next=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; if(j+1ad

20、jno=i*G.colnum+j+1; p-next=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; if(i-1=0&j-1=0&mazei-1j-1=0) p=(listnode *)malloc(sizeof(listnode); p-adjno=(i-1)*G.colnum+j-1; p-next=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; if(i-1=0&j+1adjno=(i-1)*G.colnum+j+1; p-next=G.vexsi*G.colnum+

21、j.first; G.vexsi*G.colnum+j.first=p; if(i+1=0&mazei+1j-1=0) p=(listnode *)malloc(sizeof(listnode); p-adjno=(i+1)*G.colnum+j-1; p-next=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; if(i+1G.colnum&j+1adjno=(i+1)*G.colnum+j+1; p-next=G.vexsi*G.colnum+j.first; G.vexsi*G.colnum+j.first=p; return(

22、G); /* 用int travgraph()函数广度优先遍历无向图*/int travgraph(adjlist G,int record,int entry,int exit)listnode *p; int queueMAX*MAX,visitedMAX*MAX; /*用visited数组标记图的结点是否遍历过*/ int i; int front=0,rear=1; for(i=0;iadjno=0) visitedp-adjno=1; recordp-adjno=queuefront+1; queue+rear=p-adjno; if(p-adjno=exit) goto end;

23、p=p-next; front=front+1; end:; /*用回溯法找到从出口到入口的路径,并输出*/void output (int record,int entry,int exit) int i=0,t; if(entry=exit&G.vexsexit.data=0) printf(Its already at exportn); else if(recordexit!=-1) t=exit; printf(The most short path is as follows:n); while(t!=entry) printf(%d,%d-,t/G.colnum+1,t%G.co

24、lnum+1); t=recordt; if(+i%5=0)printf(n); printf(%d,%d,t/G.colnum+1,t%G.colnum+1); else printf(Have no path from the entrance to the exitn); void main()int entry_row,entry_col,exit_row,exit_col,entry,exit; int mazeMAXMAX; int recordMAX*MAX; G=input(maze,G); G=change(maze,G); printf(Inputting the maze

25、 entrance sits the mark(*,*):); scanf(%d,%d,&entry_row,&entry_col); printf(Inputting the maze exports to sit the mark(*,*):); scanf(%d,%d,&exit_row,&exit_col); entry=-entry_row*G.colnum+-entry_col; exit=-exit_row*G.colnum+-exit_col; travgraph(G,record,entry,exit); output(record,entry,exit); getch();

26、 4.测试数据和结果 输入:行数(=15):10 列数(=15):150表示可通行,1表示不能通过。输入第1行:1 000100010001001输入第2行:2 010001010001111输入第3行:3 011111010011101输入第4行:4 110001101100101输入第5行:5 100101111010101输入第6行:6 101001010101010输入第7行:7 101111100111100输入第8行:8 111011110101010输入第9行:9 101010111010001输入第10行:10 010101000110010输入入口坐标(*,*):1,1输入出口坐标(*,*):10,15 结果:The path is as follow:10,15-9,14-8,15-7,14-6,13-5,12

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1