数据结构实验迷宫问题文档格式.docx
- 文档编号:17010414
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:20
- 大小:133.61KB
数据结构实验迷宫问题文档格式.docx
《数据结构实验迷宫问题文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构实验迷宫问题文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
}st[MaxSize];
//定义栈
inttop=-1//初始化栈
三、算法设计
要寻找一条通过迷宫的路径,就必须进行试探性搜索,只要有路可走就前进一步,无路可进,换一个方向进行尝试;
当所有方向均不可走时,则沿原路退回一步(称为回溯),重新选择未走过可走的路,如此继续,直至到达出口或返回入口(没有通路)。
在探索前进路径时,需要将搜索的踪迹记录下来,以便走不通时,可沿原路返回到前一个点换一个方向再进行新的探索。
后退的尝试路径与前进路径正好相反,因此可以借用一个栈来记录前进路径。
方向:
每一个可通点有4个可尝试的方向,向不同的方向前进时,目的地的坐标不同。
预先把4个方向上的位移存在一个数组中。
如把上、右、下、左(即顺时针方向)依次编号为0、1、2、3.其增量数组move[4]如图3所示。
move[4]
x
y
-1
1
2
3
图2数组move[4]
方位示意图如下:
通路:
通路上的每一个点有3个属性:
一个横坐标属性i、一个列坐标属性j和一个方向属性di,表示其下一点的位置。
如果约定尝试的顺序为上、右、下、左(即顺时针方向),则每尝试一个方向不通时,di值增1,当d增至4时,表示此位置一定不是通路上的点,从栈中去除。
在找到出口时,栈中保存的就是一条迷宫通路。
(1)下面介绍求解迷宫(xi,yj)到终点(xe,ye)的路径的函数:
先将入口进栈(其初始位置设置为—1),在栈不空时循环——取栈顶方块(不退栈)①若该方块为出口,输出所有的方块即为路径,其代码和相应解释如下:
intmgpath(intxi,intyi,intxe,intye)//求解路径为:
(xi,yi)->
(xe,ye)
{
struct
{
inti;
//当前方块的行号
intj;
//当前方块的列号
intdi;
//di是下一可走方位的方位号
}st[MaxSize];
//定义栈
inttop=-1;
//初始化栈指针
inti,j,k,di,find;
top++;
//初始方块进栈
st[top].i=xi;
st[top].j=yi;
st[top].di=-1;
mg[1][1]=-1;
while(top>
-1)//栈不空时循环
{
i=st[top].i;
j=st[top].j;
di=st[top].di;
//取栈顶方块
if(i==xe&
&
j==ye)//找到了出口,输出路径
{
printf("
迷宫路径如下:
\n"
);
for(k=0;
k<
=top;
k++)
{
printf("
\t(%d,%d)"
st[k].i,st[k].j);
if((k+1)%5==0)//每输出每5个方块后换一行
printf("
}
return
(1);
//找到一条路径后返回1
}
②否则,找下一个可走的相邻方块若不存在这样的路径,说明当前的路径不可能走通,也就是恢复当前方块为0后退栈。
若存在这样的方块,则其方位保存在栈顶元素中,并将这个可走的相邻方块进栈(其初始位置设置为-1)
求迷宫回溯过程如图4所示
}
从前一个方块找到相邻可走方块之后,再从当前方块找在、相邻可走方块,若没有这样的方快,说明当前方块不可能是从入口路径到出口路径的一个方块,则从当前方块回溯到前一个方块,继续从前一个方块找可走的方块。
为了保证试探的可走的相邻方块不是已走路径上的方块,如(i,j)已经进栈,在试探(i+1,j)的下一方块时,又试探道(i,j),这样会很悲剧的引起死循环,为此,在一个方块进栈后,将对应的mg数组元素的值改为-1(变为不可走的相邻方块),当退栈时(表示该方块没有相邻的可走方块),将其值恢复0,其算法代码和相应的解释如下:
find=0;
while(di<
4&
find==0)//找下一个可走方块
di++;
switch(di)
case0:
i=st[top].i-1;
break;
case1:
i=st[top].i;
j=st[top].j+1;
case2:
i=st[top].i+1;
case3:
i=st[top].i,j=st[top].j-1;
if(mg[i][j]==0)find=1;
//找到下一个可走相邻方块
if(find==1)//找到了下一个可走方块
st[top].di=di;
//修改原栈顶元素的di值
top++;
//下一个可走方块进栈
st[top].i=i;
st[top].j=j;
st[top].di=-1;
mg[i][j]=-1;
//避免重复走到该方块
else//没有路径可走,则退栈
mg[st[top].i][st[top].j]=0;
//让该位置变为其他路径可走方块
top--;
//将该方块退栈
}
return(0);
//表示没有可走路径,返回0
(2)求解主程序
建立主函数调用上面的算法,将mg和st栈指针定义为全局变量
voidmain()
mgpath(1,1,M,N);
四、界面设计
设计很简单的界面,输出路径。
五、运行测试与分析
图5.基本运行结果
六、实验收获与思考
思考:
8个方向的问题
1.设计思想
(1)设置一个迷宫节点的数据结构。
(2)建立迷宫图形。
(3)对迷宫进行处理找出一条从入口点到出口点的路径。
(4)输出该路径。
(5)打印通路迷宫图。
当迷宫采用二维数组表示时,老鼠在迷宫任一时刻的位置可由数组的行列序号i,j来表示。
而从[i],[j]位置出发可能进行的方向见下图7.如果[i],[j]周围的位置均为0值,则老鼠可以选择这8个位置中的任一个作为它的下一位置。
将这8个方向分别记作:
E(东)、SE(东南)、S(南)SW(西南)W(西)、NW(西北)、N(北)和NE(东北)。
但是并非每一个位置都有8个相邻位置。
如果[i],[j]位于边界上,即i=1,或i=m,或j=1,或j=n,则相邻位置可能是3个或5个为了避免检查边界条件,将数组四周围用值为1的边框包围起来,这样二维数组maze应该声明为maze[m+2],[n+2]在迷宫行进时,可能有多个行进方向可选,我们可以规定方向搜索的次序是从东(E)沿顺时针方向进行。
为了简化问题,规定[i],[j]的下一步位置的坐标是[x],[y],并将这8个方位伤的x和y坐标的增量预先放在一个结构数组move[8]中(见图8)。
该数组的每个分量有两个域dx和dy。
例如要向东走,只要在j值上加上dy,就可以得到下一步位置的[x],[y]值为[i],[j+dy]。
于是搜索方向的变化只要令方向值dir从0增至7,便可以从move数组中得到从[i],[j]点出发搜索到的每一个相邻点[x],[y]。
x=i+move[dir].dx
y=j+move[dir].dy
图7方向位移图图8向量差图
为了防止重走原路,我们规定对已经走过的位置,将原值为0改为-1,这既可以区别该位置是否已经走到过,又可以与边界值1相区别。
当整个搜索过程结束后可以将所有的-1改回到0,从而恢复迷宫原样。
这样计算机走迷宫的方法是:
采取一步一步试探的方法。
每一步都从(E)开始,按顺时针对8个方向进行探测,若某个方位上的maze[x],[y]=0,表示可以通行,则走一步;
若maze[x],[y]=1,表示此方向不可通行须换方向再试。
直至8个方向都试过,maze[x],[y]均为1,说明此步已无路可走,需退回一步,在上一步的下一个方向重新开始探测。
为此需要设置一个栈,用来记录所走过的位置和方向(i,j,dir)。
当退回一步时,就从栈中退出一个元素,以便在上一个位置的下一个方向上探测,如又找到一个行进方向,则把当前位置和新的方向重新进栈,并走到新的位置。
如果探测到x=m,y=n,则已经到达迷宫的出口,可以停止检测,输出存在栈中的路径;
若在某一位置的8个方向上都堵塞,则退回一步,继续探测,如果已经退到迷宫的入口(栈中无元素),则表示此迷宫无路径可通行。
2系统算法(伪代码描述):
(1)建立迷宫节点的结构类型stack[]。
(2)入迷宫图形0表示可以通1表示不可以通。
用二维数组maze[m+2][n+2]进行存储。
数组四周用1表示墙壁,其中入口点(1,1)与出口点(m,n)固定。
(3)函数path()对迷宫进行处理,从入口开始:
While(!
((s->
top==-1)&
(dir>
=7)||(x==M)&
(y==N)&
(maze[x][y]==-1)))
For(扫描八个可以走的方向)
If(找到一个可以走的方向)
进入栈
标志在当前点可以找到一个可以走的方向
避免重复选择maze[x][y]=-1
不再对当前节点扫描
If(八个方向已经被全部扫描过,无可以通的路)
标志当前节点没有往前的路
后退一个节点搜索
If(找到了目的地)
输出路径退出循环
未找到路径
(4)输出从入口点到出口点的一条路径。
(5)输出标有通路的迷宫图。
3.算法流程图:
4.程序代码:
#defineM212/*M2*N2为实际使用迷宫数组的大小*/
#defineN211
#definemaxlenM2//栈长度
#include<
stdio.h>
#include<
iostream.h>
malloc.h>
intM=M2-2,N=N2-2;
//M*N迷宫的大小
typedefstruct//定义栈元素的类型
intx,y,dir;
}elemtype;
typedefstruct//定义顺序栈
elemtypestack[maxlen];
inttop;
}sqstktp;
structmoved
//定义方向位移数组的元素类型对于存储坐标增量的方向位移数组move
{intdx,dy;
////////////////////////////////////////////////////////////////////////////////////////////////////
voidinimaze(intmaze[][N2])////初始化迷宫
inti,j,num;
for(i=0,j=0;
i<
=M+1;
i++)//设置迷宫边界
maze[i][j]=1;
j<
=N+1;
j++)
for(i=M+1,j=0;
cout<
<
"
原始迷宫为:
endl;
for(i=1;
=M;
i++)
for(j=1;
=N;
{
num=(800*(i+j)+1500)%327;
//根据MN的值产生迷宫
if((num<
150)&
(i!
=M||j!
=N))
maze[i][j]=1;
else
maze[i][j]=0;
cout<
maze[i][j]<
"
;
//显示迷宫
cout<
}//inimaze
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
voidinimove(structmovedmove[])//初始化方向位移数组
{//依次为East,Southeast,south,southwest,west,northwest,north,northeast
move[0].dx=0;
move[0].dy=1;
move[1].dx=1;
move[1].dy=1;
move[2].dx=1;
move[2].dy=0;
move[3].dx=1;
move[3].dy=-1;
move[4].dx=0;
move[4].dy=-1;
move[5].dx=-1;
move[5].dy-=1;
move[6].dx=-1;
move[6].dy=0;
move[7].dx=-1;
move[7].dy=1;
}//
voidinistack(sqstktp*s)/*初始化栈*/
s->
top=-1;
}/*inistack*/
intpush(sqstktp*s,elemtypex)
if(s->
top==maxlen-1)
return(false);
else
s->
stack[++s->
top]=x;
/*栈不满,执行入栈操作*/
return(true);
}/*push*/
elemtypepop(sqstktp*s)/*栈顶元素出栈*/
elemtypeelem;
top<
0)//如果栈空,返回空值
elem.x=NULL;
elem.y=NULL;
elem.dir=NULL;
return(elem);
top--;
return(s->
stack[s->
top+1]);
//栈不空,返回栈顶元素
}//pop
////////////////////////////////////////////////////////////////////////////////////
voidpath(intmaze[][N2],structmovedmove[],sqstktp*s)//寻找迷宫中的一条通路
inti,j,dir,x,y,f;
i=1;
j=1;
dir=0;
maze[1][1]=-1;
//设[1][1]为入口处
do
x=i+move[dir].dx;
//球下一步可行的到达点的坐标
y=j+move[dir].dy;
if(maze[x][y]==0)
elem.x=i;
elem.y=j;
elem.dir=dir;
f=push(s,elem);
//如果可行将数据入栈
if(f==false)//如果返回假,说明栈容量不足
cout<
栈长不足"
i=x;
j=y;
maze[x][y]=-1;
else
if(dir<
7)
dir++;
else
elem=pop(s);
//8个方向都不行,回退
if(elem.x!
=NULL)
{
i=elem.x;
j=elem.y;
dir=elem.dir+1;
}
}while(!
(maze[x][y]==-1)));
//循环
if(s->
top==-1)//若是入口,则无通路
此迷宫不通"
elem.x=x;
elem.y=y;
elem.dir=dir;
//将出口坐标入栈
f=push(s,elem);
迷宫通路是:
i=0;
while(i<
=s->
top)
("
s->
stack[i].x<
"
stack[i].y<
)"
//显示迷宫通路
if(i!
=s->
-->
if((i+1)%4==0)
i++;
//////////////////////////////////////////////////////////////////////////////
voiddraw(intmaze[][N2],sqstktp*s)//在迷宫中绘制出通路
逃逸路线为:
inti,j;
i++)//将迷宫中全部的-1值回复为0值
for(j=1;
if(maze[i][j]==-1)
while(s->
top>
-1)//根据栈中元素的坐标,将通路的各个点的值改为8
i=elem.x;
j=elem.y;
maze[i][j]=8;
for(i=1;
for(j=1;
%3d"
maze[i][j]);
//显示已标记通路的迷宫
voidmain()//寻找迷宫通路程序
sqstktp*s;
intmaze[M2][N2];
structmovedmove[8];
inimaze(maze);
//初始化迷宫数组
s=(sqstktp*)malloc(sizeof(sqstktp));
inistack(s);
//初始化栈
inimove(move);
//初始化方向位移数组
path(maze,move,s);
//寻找迷宫通路
draw(maze,s);
//绘制作出通路标记的迷宫
5.运行结果
收获:
这次试验总体来说还是比较简单的,因为几个思考问题都是在基本问题的源代码上进行改进和补充。
有了第一次数据结构编程和测试的经验,这次试验减少了很多困难,相对来说容易多了。
这次实验让我对栈和队列有了更好的理解和运用。
教师评分:
教师签字:
公司印章管理制度
一、目的
公司印章是公司对内对外行使权力的标志,也是公司名称的法律体现,因此,必须对印章进行规范化、合理化的严格管理,以保证公司各项业务的正常运作,由公司指定专人负责管理。
二、印章的种类
1、公章,是按照政府规定,由主管部门批准刻制的代表公司权力的印章。
2、专用章,为方便工作专门刻制的用于某种特定用途的印章,如:
合同专用章、财务专用章、业务专用章、仓库签收章等。
3、手章(签名章),是以公司法人代表名字刻制的用于公务的印章。
三、印章的管理规定
1、印章指定专人负责保管和使用,保管印章的地方(桌、柜等)要牢固加锁,印章使用后要及时收存。
2、财务专用章由财务部负责保管,向银行备案的印章,应由财务部会计、总经办分别保管。
3、印章要注意保养,防止碰撞,还要及时清洗,以保持印迹清晰。
4、一般情况下不得将印章携出公司外使用,如确实因工作所需,则应由印章管理员携带印章到场盖章或监印。
5、印章管理人员离职或调任时,须履行印章交接手续。
四、公章刻制
印章需本公司法人代表批准,并由印章管理专责人负责办理刻制并启用并交由专人进行保管。
五、印章的使用
1、使用任何的印章,需由相应负责人审核签字。
为方便工
作,总经理可授权印章管理专责人审核一般性事务用印。
2、用印前印章管理人员须认真审核,明确了解用印的内容和目的,确
认符合用印的手续后,在用印登记簿上逐项登记,方可盖章。
3、对需要留存的材料,盖印后应留存一份立卷归档。
4、不得在空白凭证、便笺上盖章。
5、上报有关部门的文件资料,未经部门经理、总经理审签,不得盖章。
6、以公司名义行文,未经总经理签发,不得盖章。
7、按照合同会签制度的规定,所有合同和协议在会签手续齐全后方可盖章。
8、各印章管理人员如出差,应把印章移交有关人员,并办理有关交接手续。
六、印章管理人员的责任
1、印章管理人员要与公司签订《印章管理责任书》,并在“印章管理制度”上签名。
2、印章管理人员不得擅自使用印章,对于非法使用印章者,造成经济损失的除赔偿损失外,还要追究其行政责任或法律责任。
用章申请
事由:
部门负责人核准
时间
副经理核准
总经理核准
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 迷宫 问题
![提示](https://static.bdocx.com/images/bang_tan.gif)