栈的基本应用之一,解决迷宫问题,主要是利用栈的递归作用。
就是个搜索加回溯,写了两遍,第一遍小问题调到两点没调试出来,第二天干脆重新写了,一次就出来了。
后面几个例子运行了下没什么问题,可能有些问题暂时没发现,主要不像OJ,人家已经把数据构造好了,自己就懒的去构造数据了
例子代码:
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define Initstacksize 100
#define Increase 100
typedef struct PosType //坐标
{
int x;
int y;
}PosType;
typedef struct MazeType
{
char **maze; //迷宫图
int **mark; //标记位
int row; //迷宫行数
int col; //迷宫列数
}MazeType;
typedef struct SElemType
{
int ord; //走的步数
PosType seat; //坐标信息
int dir; //方向
}SElemType;
typedef struct SqStack //栈
{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
void CreatMaze(MazeType &ma) //构造迷宫
{
int i,j;
char ch;
printf("Input the row and the col of the maze:\n");
scanf("%d%d",&ma.row,&ma.col);
ma.maze=(char**)malloc(Initstacksize*sizeof(char*));
ma.mark=(int**)malloc(Initstacksize*sizeof(int*));
ch=getchar();
for(i=0;i<ma.row;i++)
{
ma.maze[i]=(char*)malloc(Initstacksize*sizeof(char));
ma.mark[i]=(int*)malloc(Initstacksize*sizeof(int));
gets(ma.maze[i]);
for(j=0;j<ma.col;j++)
ma.mark[i][j]=0;
}
}
void DisplayMaze(MazeType ma) //迷宫验证
{
int i,j;
for(i=0;i<ma.row;i++)
{
for(j=0;j<ma.col;j++)
printf("%c",ma.maze[i][j]);
printf("\n");
}
}
void InitStack(SqStack &s) //初始化栈
{
s.top=s.base=(SElemType*)malloc(Initstacksize*sizeof(SElemType));
s.stacksize=Initstacksize;
}
int PassOk(PosType std,MazeType maa) //该点是否能通过
{
if(std.x<0 || std.y<0 || std.x>=maa.row || std.y>=maa.col || maa.maze[std.x][std.y]=='#' || maa.mark[std.x][std.y]>0)
return 0;
else return 1;
}
SElemType UpdatE(PosType p,int step,int di) //更新坐标信息:坐标,步数,寻找方向
{
SElemType ee;
ee.ord=step;
ee.dir=di;
ee.seat=p;
return ee;
}
void PushStack(SqStack &S,SElemType ee) //入栈
{
if(S.top-S.top>=S.stacksize)
{
S.base=(SElemType*)realloc(S.base,(Increase+Initstacksize)*sizeof(SElemType));
S.top=S.base+S.stacksize;
S.stacksize+=Increase;
}
*S.top++=ee;
}
bool EmptyStack(SqStack S) //判断栈是否为空
{
if(S.base==S.top) return true;
else return false;
}
void MakePrint(MazeType &maa,PosType p) //可行路径的记录
{
maa.mark[p.x][p.y]=1;
}
PosType NextPos(PosType p,int di) //下一步行走
{
PosType np;
np=p;
switch(di)
{
case 1:np.x++;break; //下
case 2:np.y++;break; //右
case 3:np.x--;break; //上
case 4:np.y--;break; //左
default:break;
}
return np;
}
void PopStack(SqStack &ss,SElemType &ee) //上一个点出栈 回退上一个点
{
ss.top--;
ee=*ss.top;
}
void NoPrint(MazeType &maa,PosType p) //寻找过程中的无效路径标记
{
maa.mark[p.x][p.y]=2;
}
int MazePath(MazeType ma,SqStack &s,PosType st,PosType ed) //迷宫行走
{
PosType curpos;
SElemType e;
int curstep;
curstep=1;
curpos=st;
if(!PassOk(st,ma)) return 0;//起点坐标OK
MakePrint(ma,curpos); //做路径标记
e=UpdatE(curpos,curstep,1); //更新坐标信息
PushStack(s,e); //起点入栈,作为回溯点
curpos=NextPos(curpos,1); //走下一步
curstep++;
while(!EmptyStack(s))
{
if(PassOk(curpos,ma))
{
MakePrint(ma,curpos);
e=UpdatE(curpos,curstep,1);
PushStack(s,e);
if(curpos.x==ed.x&& curpos.y==ed.y) return 1; //到达终点
curpos=NextPos(curpos,1);
curstep++;
}
else
{
if(!EmptyStack(s))
{
PopStack(s,e); //回退
while(e.dir==4 && !EmptyStack(s)) //四个方向搜索过,都是无效点
{
NoPrint(ma,e.seat); //探索过的无效路径
PopStack(s,e);
}
if(e.dir<4) //走完四个方向
{
e.dir++;
PushStack(s,e); //因为有其他方向还没走过,所以回退的节点需要重新进栈,然后去探索下个节点
curpos=NextPos(e.seat,e.dir); //下一个位置
}
}//if
}//else
}//while
return 0;
}
void DisplayMarkPath(MazeType maa) //打印路径,
{
int i,j;
for(i=0;i<maa.row;i++)
{
for(j=0;j<maa.col;j++)
printf("%d",maa.mark[i][j]);
printf("\n");
}
}
int main()
{
MazeType Maze;
SqStack stack;
PosType start,end;
int Ok;
CreatMaze(Maze); //构造迷宫
printf("///\n");
DisplayMaze(Maze); //验证构造迷宫
printf("///\n");
InitStack(stack); //初始化栈
printf("Input the start point and end point:\n");
scanf("%d%d",&start.x,&start.y);
scanf("%d%d",&end.x,&end.y); //输入起点和终点
Ok=MazePath(Maze,stack,start,end); //迷宫路径寻找
if(Ok)
{
printf("Find the way out!\n");
printf("Show the way:\n");
DisplayMarkPath(Maze);
}
else
{
printf("No way out!\n");
DisplayMarkPath(Maze);
}
return 0;
}
/*
6 5
# ###
# ###
# #
# # #
#
#####
0 1
2 4
4 5
### #
#
####
####
0 3
3 0
10 10
# ########
# # # #
# # # #
# ## #
# ### #
# # # ##
# # # #
# ### ## #
##
##########
0 1
8 9
10 10
# ########
# # # #
# # # #
# ## #
# ### #
# # # ##
# # # #
# ### ## #
## #
##########
0 1
8 8
10 10
# ########
# # # #
# # # #
# ## ##
# ### #
# # # ##
# # # #
# ### ## #
## #
##########
0 1
1 9
*/