栈的应用-迷宫

看到一个有意思的题目:给一个迷宫,并给定迷宫的起点和终点,然后求出迷宫从入口到出口的路径。

解题思路是这样:

从入口开始,每次沿逆时针方向进行判断,我们总共有四个方向(0.1.2.3),如果方向0不能走,那么我们就试方向1,一直试到可以走的方向。当某一个方向可以走的时候,我们可以往前走一格,然后再进行判断。那么,当然,我们很有可能走到一个死胡同,死胡同的定义是,除了我们来的那个方向,其他三个方向都无法走的通,此时,我们就往后退一个,退到原来的位置,在这个位置上,对之前还没有验证的其他方向进行判断。

比如当前的迷宫式这个样子的(10*10),(1,1)位置是起点,(8,8)位置是终点,X是墙,+是走过得路径,O是小人。当前O所在的位置是(1,7),假设我们定义左边为方向0,逆时针判断,此时,是一个死胡同,我们就要向后退一个。

image

 

具体的算法是这样:

有一个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头文件

运行效果如下:

image

image

 

(本文网址:http://www.cnblogs.com/marsdu/p/3186849.html

posted @ 2013-07-12 18:26  immars!  阅读(545)  评论(0编辑  收藏  举报