迷宫问题文档格式.docx
《迷宫问题文档格式.docx》由会员分享,可在线阅读,更多相关《迷宫问题文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
{
introw;
intcol;
};
typedefdotDT;
structnode
DTdot;
node*next;
typedefnode*STACK;
STACKMakeNull()
STACKS;
S=newnode;
S->
next=NULL;
returnS;
}
voidPush(DTdotx,STACKS)
STACKstk;
stk=newnode;
stk->
dot=dotx;
next=S->
next;
next=stk;
//删除栈顶
voidPop(STACKS)
if(S->
next)
{
stk=S->
next=stk->
deletestk;
}
DTTop(STACKS)
DTNU;
NU.row=-1;
NU.col=-1;
return(S->
next->
dot);
else
returnNU;
voidCreatmaze(int(*maze)[MAXCOL],inta,intb)
inti=0,j=0;
srand(time(NULL));
for(i=0;
i<
=a+1;
i++)
for(j=1;
j<
=b+1;
j++)
if(i==0||i==a+1||j==0||j==b+1)
maze[i][j]=1;
if(rand()%3==0)
maze[i][j]=0;
maze[1][1]=0;
maze[a][b]=0;
printf("
\n\n生成的迷宫如下图所示:
\n\t"
);
for(i=1;
=a;
=b;
if(maze[i][j])
■"
□"
DTNext(DTdotp,int(*a)[MAXCOL])
DTdotq;
intx,y;
x=dotp.row;
y=dotp.col;
if(a[x][y]==1)
dotq.row=x;
dotq.col=y;
if(a[x+1][y]==0)
dotq.row=x+1;
a[x][y]=4;
//s2=s2+1;
elseif(a[x][y+1]==0)
dotq.col=y+1;
a[x][y]=6;
//s2=s2+2;
elseif(a[x-1][y]==0)
dotq.row=x-1;
a[x][y]=3;
//s2=s2+3;
elseif(a[x][y-1]==0)
dotq.col=y-1;
a[x][y]=5;
//s2=s2+4;
a[x][y]=2;
returndotq;
intDTcp(DTdot1,DTdot2)
if(dot1.row==dot2.row&
&
dot1.col==dot2.col)
return1;
return0;
intFindway(STACKS,int(*maze)[MAXCOL],inta,intb)
//s1++;
intret=1;
DTdot_out,dottemp;
dot_out.row=a;
dot_out.col=b;
if(maze[1][1]==2)
\n找不到路径\n"
ret=0;
if(DTcp(Top(S),dot_out))
maze[Top(S).row][Top(S).row]=6;
dottemp=Next(Top(S),maze);
if(DTcp(dottemp,Top(S)))
Pop(S);
Push(dottemp,S);
ret=Findway(S,maze,a,b);
returnret;
voidInverse(STACKS1,STACKS2)
while(S1->
dot=Top(S1);
Push(dot,S2);
Pop(S1);
voidGivepath(int(*maze)[MAXCOL],inta,intb)
inti,j;
\n\n从(1,1)处沿着箭头给出的轨道前进即可:
switch(maze[i][j])
case1:
break;
case3:
↑"
case4:
↓"
case5:
←"
case6:
→"
default:
voidDisplay(STACKS)
STACKS2=MakeNull();
Inverse(S,S2);
STACKtemp=S2->
intk=0;
\n"
do
\t第%2d步:
点(%d,%d)\n"
k,temp->
dot.row,temp->
dot.col);
temp=temp->
k=k+1;
while(temp->
next);
\t共%2d步"
k);
intmain()
intmaze[MAXROW][MAXCOL];
inta=6,b=6;
intret,ret1,ret2;
DTdot_in;
dot_in.row=1;
//全局变量的定义
dot_in.col=1;
STACKS=MakeNull();
\n请输入要生成的迷宫行数(20以内):
\t"
fflush(stdin);
ret1=scanf("
%d"
&
a);
if(!
ret1||a<
=1||a>
20)
\n不合要求,请输入行数(20以内):
while(!
20);
\n请输入要生成的迷宫列数(20以内):
ret2=scanf("
b);
ret2||b<
=1||b>
\n不合要求,请输入列数(20以内):
//s1=0;
//s2=0;
Creatmaze(maze,a,b);
Push(dot_in,S);
maze[dot_in.row][dot_in.col]=3;
ret=Findway(S,maze,a,b);
//printf("
\n\ns1=%d,s2=%d:
"
s1,s2);
ret)
\n按任意键重给一个迷宫:
getch();
ret);
\n\n已找到一条路径。
按任意键给出此路径:
Display(S);
Givepath(maze,a,b);
主要数据结构
1.一个用于表示迷宫内容的二维数组maze[][]。
相关操作有:
(1)建立二维数组,赋初值。
(Creatmaze)
(2)数组以指针形式在各函数中传递。
(3)改变数组中某个元素的值。
2.一个表示所选路径的栈S。
(1)以指针实现的方式,建立空栈。
(MakeNull)
(2)压栈操作。
(Push)
(3)返回栈顶的操作。
(Top)
(4)弹栈操作。
(Pop)
(5)将栈中各元素逆序排列。
(Inverse)
(6)栈的遍历,输出各元素。
(Display)
3.结构体DT记录点的行数与列数;
一个结构体对应一个点
4.结构体Node栈S的一个结点
主要功能
1.用户输入迷宫的行与列,给出一个迷宫。
2.寻找一条能走出迷宫的路径。
3.若不存在这样的路径,给出提示并重新建立一个迷宫。
若存在路径,将当前找到的路径输出。
程序介绍
1.函数Creatmaze(maze,a,b):
产生迷宫。
按2:
1的比例得到迷宫中的通路与阻隔。
Rand()被3整除时该点设为阻隔,否则该点设为通路。
2.函数Findway(S,maze,a,b):
寻找路径。
函数中利用了递归的方法,处理完当前点之后,再使用函数Findway自身,直至当前点为出口点。
›内部含一函数Next(),负责返回下一点的坐标,并判断下一点在当前点的上下左右哪一方位,在当前点做出标记。
若当前点周围没有可行点,返回值为当前点的坐标。
›返回点是当前点(表示此路不通),将当前点对应的数组元素赋值为2;
›返回点在当前点上方,将当前点对应的数组元素赋值为3;
›返回点在当前点下方,将当前点对应的数组元素赋值为4;
›返回点在当前点左方,将当前点对应的数组元素赋值为5;
›返回点在当前点右方,将当前点对应的数组元素赋值为6;
3.函数Givepath(maze,a,b):
根据maze记录的每个点处的路径的走向,给出路径图。
4.函数Display(S):
根据S记录的先后顺序,给出走出迷宫的路径。
›内部含一函数Inverse(),负责将S中的元素逆序。
这是因为S本来是以最后一步为栈顶的,第一步在栈底。
为了使输出是正序的,应先将S中的元素逆序排列。
算例
1.输入行数与列数。
2.第一次生成迷宫,无通路。
3.再生成一次,有通路。
4.给出路径。
(截图太大,下页续)
程序性能分析
程序中最耗时的操作是“搜寻下一点”。
应以“搜寻”次数表征其复杂度。
最糟糕的情况是“搜寻”时多次前进、退回,即压栈、弹栈。
对于一个m*n的迷宫,其时间复杂度的上限为(m*n)^3.
由于出口位于入口的右下方,所以搜寻时优先选择向下、向右。
这样有助于寻找最短路径(当然并不一定是最短路径),也节约了时间。
这样一来,实际上每次执行Next函数,并不需要3次判断。
对此问题而言,这样做是十分合理的。
在存储上,只使用了一个数组,采取了对原数组的元素值重新赋值的“覆盖式”方法,而不是重建一个数组专门保存新赋的值。
这样节约了空间,代价是不能直接记录原迷宫的形状了。
对此问题而言,这样做是合理的。
注:
源代码中定义了两个静态变量s1,s2。
每次运行函数Findway,s1++;
每次考察点是否为可行点s2++。
(现在已经用//注释掉)
各做10次实验结果表明:
取m=n=20时,s1,s2为
次数
1
2
3
4
5
6
7
8
9
10
S1
123
484
372
93
45
366
26
298
478
S2
175
613
443
128
567
63
438
23
369
584
通路有无
无
有
取m=n=10时,s1,s2为
20
35
78
21
142
134
66
168
16
53
82
31
170
145
29
70
210
这表明程序的时间复杂度实际上远达不到(m*n)^3。
这与源代码中按下、右、上、左、的顺序依次搜寻时有关的。