迷宫问题的CC算法实现讲解.docx
- 文档编号:23923916
- 上传时间:2023-05-22
- 格式:DOCX
- 页数:16
- 大小:21.23KB
迷宫问题的CC算法实现讲解.docx
《迷宫问题的CC算法实现讲解.docx》由会员分享,可在线阅读,更多相关《迷宫问题的CC算法实现讲解.docx(16页珍藏版)》请在冰豆网上搜索。
迷宫问题的CC算法实现讲解
基于栈的c语言迷宫问题与实现
1.问题描述
多年以来,迷宫问题一直是令人感兴趣的题目。
实验心理学家训练老鼠在迷宫中寻找食物。
许多神秘主义小说家也曾经把英国乡村花园迷宫作为谋杀现场。
于是,老鼠过迷宫问题就此产生,这是一个很有趣的计算机问题,主要利用“栈”是老鼠通过尝试的办法从入II穿过迷宫走到出口。
迷宫只有两个门,一个叫做入口,另一个叫做出口。
把一只老鼠从一个无顶盖的人盒子的入11处赶进迷宫。
迷宫中设置很多隔壁,对前进方向形成了多处障碍,在迷宫的唯一出11处放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出II。
求解迷宫问题,即找出从入II到出口的路径。
一个迷宫可用上图所示方阵[ni,n]表示,0表示能通过,1表示不能通过。
现假设耗子从左上角[1,1]进入迷宫,编写算法,寻求一条从右下角[m,n]出去的路径。
下图是一个迷宫的示意图:
2.算法基本思想
迷宫求解问题是栈的一个典型应用。
基本算法思想是:
在某个点上,按照一定的顺序(在本程序中顺序为上、右、下、左)对周围的墙、路进行判断(在本程序中分别用1、0〉代替,若周围某个位置为0,则移动到该点上,再进行卞一次判断;若周围的位置都为1(即没有通路),则一步步原路返回并判断有无其他通路,然后再次进行相同的判断,直到走到终点为止,或者确认没有任何通路后终止程序。
要实现上述算法,需要用到栈的思想。
栈里面压的是走过的路径,若遇到死路,则将该位置(在栈的顶层)弹出,再进行下一次判断;若遇到通路,则将该位置压栈并进行卞一次判断。
如此反复循坏,直到程序结束。
此时,若迷宫有通路,则栈中存储的是迷宫通路坐标的倒序排列,再把所有坐标顺序打印后,即可得到正确的迷宫通路。
3.程序具体部分的说明
1.迷宫的生成
根据题目的要求,迷宫的人小是自定义输入的。
所以在程序中用malloc申请动态二维数组。
数组中的元素为随机生成的0、lo数组周闱一圈的元素全部定义为1,以表示边界。
2.栈的C语言实现
为了实现栈的功能,即清空、压栈、弹出、返回栈顶元素,在程序中编写了相应的函数。
MakeNULL清空栈
Push将横、纵坐标压栈
Topx返回栈顶存储的横坐标
Topy返回栈顶存储的纵坐标
Pop弹出栈顶元素
3.具体的判断算法
当位置坐标(程序中为XY)移到某一位置时,将这个位置的值赋值为1并压栈,以说明该点已经走过。
接着依次判断该点的上、右、下、左是否为0,若有一方为0,则移动到该位置上,进行下次判断;若为周I制位置全部是1,则将该点压栈后不断弹出,每次弹出时判断栈顶元素(即走过的路)周闱有无其他通路。
如果有的话,则选择该方向继续走下去;如果栈已经为空仍然没有找到出路,则迷宫没有出II程序结束。
当XY走到出II坐标时,程序判断部分结束。
栈里面存储的是每个走过的点的坐标,将这些横纵坐标分别存储在两个数组中,最后将数组中的坐标元素倒序输出,即得到了完整的路径。
4.程序源代码及注释
//Maze.cpp:
定义控制台应用程序的入口点。
//
★include"stdafx.h"
#incIude〈stdio.h>
#incIude〈string.h>
#include〈malloc.h>
#incIude
#incIude
typedefintElementtype;
struetnode
{
EIementtypeva11;
EIementtypeval2;
node*next;
};//定义结构体
typedefnode*MAZE;
voidMakeNulI(MAZE&S);
voidPush(EIementtypexrElementtypey,MAZES);voidPop(MAZES);
ElementtypeTopx(MAZES);
ElementtypeTopy(MAZES);//申明函数
int_tmain(intargc,_TCHAR*argv[])
{""
int**p,*q,*x1f*y1,i,j,k,n1,n2,ml,m2,I.w,max;irrtx,y;
irrta,b,c,d;
printf(”输入迷宫长度及宽度I和叭n“);
scanf("%d%d",&l,&w);
getchar();
n1=w+2;
n2=l+2;//为迷宫加上边界
max=n1*n2;
p=(int**)maIIoc(n1*sizeof(int));
for(i=0;i p[i]=(int*)maIloc(n2*sizeof(int));//生成二维动态数组srand(time(NULL)); x1=(int*)maIloc(max*sizeof(int));//生成动态数组用于存储路径y1=(int*)maIloc(max*sizeof(int));//生成动态数组用于存储路径for(i=0;i { x1[i]二0; ) for(i=0;i { y1[i]二0; }//先将存储路径的数组元素全赋值为0 for(i=0;i { for(j=0;j { if(i==0||j=0) { p[i][j]二1; } elseif(i==n1-1||j==n2-1) { p[i][j]二1; } eIse p[i][j]=rand()%2+0; } }〃生成二维10随机数组 p[1][1]=0; p[n1-2][n2-2]=0;//定义迷宫的入口及出口 printfC生成的迷宫如下(代表墙0代表路): \n"); for(i=0;i for(j=0;j printf("\n"); }〃打印迷宫 MAZES; MakeNull(S);//清空栈 i=1; j=1; if(p[1][2]=1&&p⑵⑴=) { printf("Thereisnowayout");a getchar(); return0; }〃判断入口是否就是死路eIse { do y二j; Push(x,y,S);p[i][j]=;i=i-1; }//判断能否向上走 elseif(p[i-1][j]=1&&p[i][j+1]==0)y二j; Push(x,yrS);p[i][j]=;j二j+1; }//判断能否向右走 elseif(p[i-1][j]==1&&p[i][j+1]=1&&p[i+1][j]==0) y二j; Push(x,y,S);k=Topx(S);p[i][j]=;i二i+1; }〃判断能否向下走 elseif(p[i-1][j]==1&&p[i][j+1]=1&&p[i+1][j]==1&&p[i][j-1]==0) y二j; Push(x,y,S);p[i][j]=;J=J-1; }〃判断能否向左走 elseif(p[i-1][j]==1&&p[i][j+1]==1&&p[i+1][j]=1&&p[i][j-1]==1)//判断如果为死路 { p[i][j]=1; x二i; y二j; Push(x,y,S); for(;;) { Pop(S);//弹出栈顶元素 x=Topx(S); y=Topy(S);//返回栈顶元素横纵坐标 if(p[x-1][y]==0) { i=x-1; j二y; p[i][j]二1; X二i; y二j; Push(x,y,S); break; } elseif(p[x-1][y]=1&&p[x][y+1]==0) { i二x; j二y+1; p[i][j]二1; x二i; y二j; Push(x,y,S); break; } elseif(p[x-1][y]=1&&p[x][y+1]==1&&p[x+1][y]==0) { i二x+1; j二y; p[i][j]二1; x二i; y二j; Push(x,y,S); break; } elseif(p[x-1][y]==1&&p[x][y+1]=1&&p[x+1][y]=1&&p[x][y-1]==0) { i二x; j二yT; p[i][j]二1; x二i; y二j; Push(x,y,S);break; }//判断弹出后栈顶元素周围有无通路 elseif(x~1&&y~1) printf("Thereisnowayout”);getchar(); return0; }//如果栈顶元素为入口则迷宫无出路} 1 }while(i! =n1-2||j! =n2-2);//循环截止条件 ) printf("Success! \nTherouteis: \n");for(i二0;;i++) a二Topx(S); b二Topy(S); Pop(S); x1[i]二a; y1[i]二b;//将栈顶元素坐标存储在数组中 if(a~1&&b=1) { getchar(); break; 1 ) for(i二max-1;i>=0;) { if(x1[i]! 二0&&(x1[i]! =x1[i-1]||y1[i]! =y1[i-1])) { printf("<%d,%d>",x1[i],y1[i]); i—; 1 elseif(x1[i]! =0&&(x1[i]==x1[i-1]&&[订==y1[i-1])) { printf("<%d,%d>",x1[i],y1[i]); i二i-2; 1 eIse i一; }〃倒序打印数组得到顺序出路坐标 printf(H<%d,%d>",n1-2,n2-2);〃打印出口坐标 getchar(); return0; voidMakeNuII(MAZE&S)//清空栈的函数 S=newnode; S->next二NULL; } voidPush(EIementtypex,Elementtypey,MAZES)//压栈函数{ MAZEstk; stk=newnode; stk->va11二x; stk->va12二y; stk->next二S->next; S->next二stk; } voidPop(MAZES)//弹出函数 { MAZEstk; if(S->next) { stk=S->next; S->next二stk->next; deletestk; ) } ElementtypeTopx(MAZES)//返回横坐标函数 { if(S->next) return(S->next->va11); eIse returnNULL; } ElementtypeTopy(MAZES)//返回纵坐标函数 { if(S->next) return(S->next->va12); eIse returnNULL; 另一种方法实现的迷宫代码 #ifhdefMMIGONG.H #defineMMIGONG_H #defineMAX.SIZE100 #iiiclude stmctNode { liltX; mty;intdi; }; classStack { private: mtrrow; intccolin; inttop; intcount; mtmuilenght; Nodestack[MAX.SIZE]; Nodesstack[NIAX.SIZE]; public: Stack();//初始化 //int**InsonMiGong();〃输入迷宫(即一个二维数组)voidFindPath(intab[][10]);〃找出迷宫的出路 }; Stack: : Stack()〃初始化 { now=0; ccohn=0; top=-l; count=l; niuilenght=NIAX_SIZE; } /*int**Stack: : InsoilMiGong()〃输入迷宫(即一个二维数组){ intTow=]£olm=]; wliile(tnie) { cout«*'请输入迷宫的行数和列数: ”; ciii»row»colin; if(row<=01|colin<=0) { cout«H输入错误! 请重新输入: n«endl; rrox^row; ccolm=colm; continue; } else { rrox^row; ccolm=colm; break; } } int*mg[]; cout«*'请输入迷宫矩阵(只有0和1两个数构成): ”; foi(mti=0;i fbr(mtj=0;j cm»mg[i]Ij];returnmg; }*/voidStack: : FindPath(intab[][10])〃找出迷宫的出路 { inta.b.di.fiiid.k; top++;stack[top].x=l; stack[top].v=l; stack[top].di=-l; ab[l][l]=-l; while(top>-l) { a=stack[top].x; b=stack[top].v; di=stack[top].di; if(a==8&&b=8) { cout«count++«,,: H«endl; fdr(intk=0;k<=top;k++) {coi】t«”(y ((k+l)%15)) cout«endl: } cout«endl; if(top+1 { for(k=0;k<=top;k++)sstack[k]=stack[k]; nunlenght=top+l; } ab[stack[top].x][stack[top].v]=0: top—;a=stack[top].x;b=stack[top].y;di=stack[top].di; } find=0; while(di<8&&! find) di++;switch(di)case0: a=stack[top].x-1;b=stack[top].y;break;case1: a=stack[top].x;b=stack[top].y+1;break;case2: a=stack[top].x+l;b=stack[top].y;break;case3: a=stack[top].x;b=stack[top].y-1;break: }if(ab[a][b]==O) find=l; stack[top].di=di;top++;stack[top].x=a;stack[top].y=b;stack[top].di=-l;ab[a][b]=-l; else ab[stack[top].x][stack[top].v]=0: } cout«endl; coutvv”走出迷宫最短的路径是: "«eiidl; cout«M其长度为: H«niuilenght«endl;cout«M路径是: H«endl; for(k=O;k cout«ll(,,«sstack[k].x«H;,«sstack[k].x«,,)n;if(k cout«H->n; if(! ((k+l)%10)) cout«endl; }cout«endl; #endif #mcludeHMMIGONG.HM Stackstack;intab[10][10]= {1,1,1,1,1,1,1,1,1,1,}, {1,OA1,0,0,0,1,OJJ, {1,0A1,0,0,0,1,OJJ, {1,000,0,1,1,0,0,1,}, {1,0,1,1,1,000,0,1,}, {1,0,0,OJA0,0.0,1,}, {1,0,1,000,1,0,0,1,}, {1,0,1,1,1,0丄1,0,1,}, {1丄0,0,0,0,0,0,0丄}, {1,1,1,1,1,1,1,1,1,1,}, }; coutvv所有可以走出迷宫的路径有: ”《endl; stack.FindPath(ab); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 问题 CC 算法 实现 讲解