栈的应用-迷宫
看到一个有意思的题目:给一个迷宫,并给定迷宫的起点和终点,然后求出迷宫从入口到出口的路径。
解题思路是这样:
从入口开始,每次沿逆时针方向进行判断,我们总共有四个方向(0.1.2.3),如果方向0不能走,那么我们就试方向1,一直试到可以走的方向。当某一个方向可以走的时候,我们可以往前走一格,然后再进行判断。那么,当然,我们很有可能走到一个死胡同,死胡同的定义是,除了我们来的那个方向,其他三个方向都无法走的通,此时,我们就往后退一个,退到原来的位置,在这个位置上,对之前还没有验证的其他方向进行判断。
比如当前的迷宫式这个样子的(10*10),(1,1)位置是起点,(8,8)位置是终点,X是墙,+是走过得路径,O是小人。当前O所在的位置是(1,7),假设我们定义左边为方向0,逆时针判断,此时,是一个死胡同,我们就要向后退一个。
具体的算法是这样:
有一个while循环,在路径栈不为空的时候,一直在循环:
do { if(若当前位置可通) { 将当前位置插入栈顶 if(当前位置是出口位置) 结束 else 切换当且位置的第1方向方块位当前位置 }else { if(栈不为空&&栈顶位置尚有其他方向未探索) 去栈顶方块的下一个方向的相邻方块作为当前方块 else if(栈不为空&&其他位置皆不可通) { 删去栈顶位置; if(栈不为空) 重新测试新的栈顶位置,直到找到一个可通的相邻块或出栈至栈空; } } }while(栈不为空)
下面是实现的代码:
/** *stack.h */ #ifndef _STACK_H #define _STACK_H #include "data.h" #define STACK_INIT_SIZE 10 #define STACK_INCREME 10 typedef struct { ElemType *base; ElemType *top; int size; }STACK; STACK * InitStack(); void DestroyStack(STACK *s); int Push(STACK *s,ElemType *e); int Pop(STACK *s,ElemType *e); int IsEmpty(STACK *s); #endif
/** *data.h */ #ifndef _DATA_H #define _DATA_H //位置坐标结构 typedef struct { int x,y; }POS; //有效的路径结构 typedef struct { int sno;//路径编号 POS seat;//路径位置 int di;//该路径的方向 }ElemType; #endif
/** *stack.cpp */ #include "stack.h" #include <iostream> STACK * InitStack() { STACK * s = (STACK *)malloc(sizeof(STACK)); if(s == NULL) exit(0); s->base = (ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType)); if(s->base == NULL) exit(0); s->top = s->base; s->size = STACK_INIT_SIZE; return s; } void DestroyStack(STACK *s) { free(s->base); free(s); } int Push(STACK *s,ElemType *e) { if(s==NULL||e==NULL) return 0; if(s->top - s->base >=s->size) { s->base = (ElemType *)realloc(s->base, (s->size + STACK_INCREME)*sizeof(ElemType)); if(s->base == NULL) return 0; s->top = s->base + s->size; s->size = s->size + STACK_INCREME; } *s->top = *e; s->top ++; return 1; } int Pop(STACK *s,ElemType *e) { if(s==NULL||e==NULL) return 0; if(s->base == s->top) return 0; *e = *(--s->top); return 1; } int IsEmpty(STACK *s) { return s->top == s->base ?1:0; }
/** *main.cpp */ #include "stack.h" #include "data.h" #include <iostream> #include <stdlib.h> #include <conio.h> using namespace std; int item[10][10]= { {1,1,1,1,1,1,1,1,1,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,0,0,1,1,0,0,1}, {1,0,1,1,1,0,0,0,0,1}, {1,0,0,0,1,0,0,0,0,1}, {1,0,1,0,0,0,1,0,0,1}, {1,0,1,1,1,0,1,1,0,1}, {1,1,0,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1,1,1} }; static const POS inPos = {1,1}, outPos ={8,8}; int IsPass(POS curP) { return item[curP.y][curP.x]==0 ? 1:0; } POS NextPos(POS curP,int di) { //0,1,2,3 POS p = curP; switch(di) { case 0: p.x--; break; case 1: p.y++; break; case 2: p.x++; break; case 3: p.y--; } return p; } void PrintItem(POS curP) { int i,j; system("cls"); for(i = 0;i<10;i++) { for(j=0;j<10;j++) { if(i==curP.y&&j==curP.x) { cout<<"O"; continue; } if(item[i][j]==2) cout<<"+"; else if (item[i][j] ==1) cout<<"X"; else cout<<" "; } cout<<endl; } } int main() { ElemType e; int step =1; POS curPos = inPos; STACK * s = InitStack(); PrintItem(inPos); do { if(IsPass(curPos)) { e.sno = step; e.di = 0; e.seat = curPos; Push(s,&e); item[curPos.y][curPos.x] = 2; if(curPos.y == outPos.y && curPos.x == outPos.x) { PrintItem(curPos); getch(); cout<<"OK"<<endl; while(!IsEmpty(s)) { ElemType r; Pop(s,&r); cout<<"("<<r.seat.x<<","<<r.seat.y<<")"; } cout<<endl; break; } PrintItem(curPos); getch(); curPos = NextPos(curPos,0); step++; } else { //先出栈(后面还会再进)获取当前路径元素 Pop(s,&e); if(e.di==4 && !IsEmpty(s)) { item[curPos.y][curPos.x]=3; Pop(s,&e); } if(e.di <=3) { e.di ++; Push(s,&e); curPos = NextPos(e.seat,e.di); } } }while(!IsEmpty(s)); return 0; }
system("cls");是清除,引用了stdlib头文件
getch(); 是暂停,引用了conio头文件
运行效果如下:
From: immars 欢迎转载,但请尊重作者劳动,转载请注明出处!