数据结构迷宫问题

此程序有小bug,修改在最后

转自:https://blog.csdn.net/qq_37414405/article/details/85935033

思路:利用栈穷举路径,从而来得到问题的解答

注意:当前路径可通,指未曾走到过的通道块(即不能是已经压入栈中的通道块又被重复压入,这样的话就不是简单路径了)。并且该通道块不能是曾经纳入过路径的通道块(即不能之前弹出了又压入进去,这样的话就会在死胡同里转圈)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

原程序:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100  //存储空间初始分配量
#define STACKINCREMENT 10  //存储空间分配增量
typedef int Status;


typedef struct
{
    int row;
    int col;
}PosType;


typedef struct
{
    int ord;  //通道块在路径上的“序号”
    PosType seat;  //通道块在迷宫中的“坐标位置”
    int di;  //从此通道块走向下一通道块的“方向”
}SElemType;

typedef struct
{
    SElemType *base;  //在栈构造之前和销毁之后,base的值为NULL
    SElemType *top;  //栈顶指针
    int stacksize;  //当前已分配的存储空间,以元素为单位
}SqStack;

int MazeMap[10][10] =    //迷宫地图为全局变量
{
   //0,1,2,3,4,5,6,7,8,9
    {0,0,0,0,0,0,0,0,0,0}, //0
    {0,1,1,0,1,1,1,0,1,0}, //1
    {0,1,1,0,1,1,1,0,1,0}, //2
    {0,1,1,1,1,0,0,1,1,0}, //3
    {0,1,0,0,0,1,1,1,1,0}, //4
    {0,1,1,1,0,1,1,1,1,0}, //5
    {0,1,0,1,1,1,0,1,1,0}, //6
    {0,1,0,0,0,1,0,0,1,0}, //7
    {0,0,1,1,1,1,1,1,1,0}, //8
    {0,0,0,0,0,0,0,0,0,0}  //9
};
//***************注意在数组中与坐标的不同表示方法,容易混淆

/*******************************声明部分****************************************/

/*******************************函数部分****************************************/
Status InitStack(SqStack *S)
{
    (*S).base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if(!(*S).base)
        exit(OVERFLOW);

    (*S).top = (*S).base;
    (*S).stacksize = STACK_INIT_SIZE;
    return OK;
}

Status Push(SqStack *S,SElemType e)
{
    *(*S).top++ = e;
    return OK;
}

Status Pop(SqStack *S,SElemType *e)
{
    if((*S).top == (*S).base)
        return ERROR;
    *e = *(--(*S).top);
    return OK;
}

Status StackEmpty(SqStack S)
{
    if(S.top==S.base)
        return OK;
    return ERROR;
}

void PrintMaze( )
{
    printf("\n 迷宫的地图为:\n\n");
    int i,j;
    for(i = 0;i&lt;10;i++){
        for(j = 0;j&lt;10;j++)
            printf(" %3d",MazeMap[i][j]);
        printf("\n");
    }
}

Status FootPrint(PosType pos,int curstep)
{
    MazeMap[pos.row][pos.col] = curstep;
    return OK;
}


Status Pass(PosType pos)
{
    if(MazeMap[pos.row][pos.col] == 1)
        return TRUE;

    return FALSE;
}

PosType NextPos(PosType CurPos,int i)
{
    switch(i)
    {
    case 1:
        ++CurPos.row;  //东
            break;
    case 2:
        ++CurPos.col;  //南
            break;
    case 3:
        --CurPos.row;  //西
            break;
    case 4:
        --CurPos.col; //北

            break;
    }//switch
    return CurPos;
}

void MakePrint(PosType pos)
{
    printf("(%d,%d)走不通\n",pos.row,pos.col);
    MazeMap[pos.row][pos.col] = 0;  //将走不通的块替换为墙壁
}

Status MazePath(PosType start,PosType end)
{
    SqStack S;
    PosType curpos;
    SElemType e;
    int curstep;

    InitStack(&amp;S);
    curpos = start; //设定“当前位置”为“入口位置”
    curstep = 1; //探索第一步
    printf("\n起点:(%d,%d)",start.row,start.col);
    do{
        if(Pass(curpos)){  //当前位置可以通过,即使未曾走到过的通道块
            FootPrint(curpos,curstep);  //留下足迹
            printf("  -&gt;(%3d,%3d)\n",curpos.row,curpos.col);
            e.ord = curstep;
            e.seat = curpos;
            e.di = 1;
            Push(&amp;S,e);  //加入路径

            if(curpos.row == end.row &amp;&amp; curpos.col == end.col){  //到达终点
                printf("到达终点:(%3d,%3d)\n",e.seat.col,e.seat.row);
                return TRUE;
            }
            curpos = NextPos(curpos,1);   //下一位置是当前位置的东邻
            curstep++;  //探索下一步
            printf("step:%d",curstep);
        }//if
        else{  //当前位置不能通过
            if(!StackEmpty(S)){

                Pop(&amp;S,&amp;e);
                while(e.di == 4 &amp;&amp; !StackEmpty(S)){
                    MakePrint(e.seat);
                    Pop(&amp;S,&amp;e);
                    curstep--;
                    printf("倒退到(%3d,%3d)\n",e.seat.col,e.seat.row);
                }//while
                if(e.di &lt; 4){
                    ++e.di;  //换下一个方向探索
                    Push(&amp;S,e);
                    curpos = NextPos(e.seat,e.di); //设定当前位置是该新方向上的相邻块
                }//if
            }//if
        }//else
    }while(!StackEmpty(S));
    printf("对不起,找不到出口\n");
    return FALSE;
}


/*******************************主函数部分**************************************/

int main()
{
    PrintMaze();
    PosType Start,End;
    Start.col = 1;
    Start.row = 1;
    End.col = 8;
    End.row = 8;
    MazePath(Start,End);
    PrintMaze();
    return 0;
}

bug:

如果把MazeMap改为:

               //0,1,2,3,4,5,6,7,8,9
                {0,0,0,0,0,0,0,0,0,0}, //0
                {0,1,1,1,1,1,1,0,1,0}, //1
                {0,1,0,1,1,1,1,0,1,0}, //2
                {0,0,1,1,1,0,0,1,1,0}, //3
                {0,1,0,1,0,1,1,1,1,0}, //4
                {0,1,1,1,0,1,1,1,1,0}, //5
                {0,1,0,1,1,1,0,1,1,0}, //6
                {0,1,0,0,0,1,0,0,1,0}, //7
                {0,0,1,1,1,1,1,1,1,0}, //8
                {0,0,0,0,0,0,0,0,0,0}  //9

则输出为:

      0    0    0    0    0    0    0    0    0    0  
      0    3    4    5    1    1    1    0    1    0  
      0    2    0    6    1    1    1    0    1    0  
      0    0    1    7    1    0    0    1    1    0  
      0    1    0    8    0    1    1    1    1    0  
      0    1    1    9    0    1    1    1    1    0  
      0    1    0   10   11   12    0    1    1    0  
      0    1    0    0    0   13    0    0    1    0  
      0    0    1    1    1   14   15   16   17    0  
      0    0    0    0    0    0    0    0    0    0 

显然不太正确,主要的问题在于,首选NextPos(,1)即当前位置能通过时,先向下探索,从(1,1)到(2,1),Pass(2,1)=1,留下足迹MazeMap[2][1]=curstep=2(注意,此时Pass(2,1)不再为1),显然(2,1)没法往后走。当di增加到3时,NextPos又回到(1,1),而MazeMap[1][1]=1(因为在(1,1)点时,curstep恰好是1)导致Pass为真,所以FootPrint(1,1,curstep=3)使MazeMap[1][1]=3,接下来由于之前FoorPrint改变了MazeMap[2][1]使之不再为1,Pass返回0,所以就不能再从(1,1)->(2,1),而是1,1)->(1,2)这就出现了上边的bug(说的我自己都糊涂了,还是一步一步推一下比较清楚)
解决的办法是不能让某一点FootPrint之后在MazeMap中的值还是1,否者就会导致无法判断是否曾经到达过这一点(因为能到达的点在MazeMap中本来就是1)。仔细分析可知,只有在起点(1,1)处才会有这个问题,因为只有这一点curstep才会是1,所以让(1,1)点FootPrint之后的值为0,如果能够找到出口,在打印路径时再把值改为1.

更改后程序如下:

//
// Created by dgm on 19-3-2.
//
#define MaxSize 1000
#define Increment 100
#include <iostream>
#include <iomanip>
using namespace std;
typedef int Status;
typedef struct {
    int row;
    int col;
}PosType;
typedef struct {
    int ord;
    PosType seat;
    int di;
}ElemType;

typedef struct Stack{
    ElemType*top;
    ElemType*base;
    unsigned int stack_size;
}Stack;

int MazeMap[10][10] =   
        {

               
                {0,0,0,0,0,0,0,0,0,0}, 
                {0,1,1,1,1,1,1,0,1,0}, 
                {0,1,0,1,1,1,1,0,1,0}, 
                {0,0,1,1,1,0,0,1,1,0}, 
                {0,1,0,1,0,1,1,1,1,0}, 
                {0,1,1,1,0,1,1,1,1,0}, 
                {0,1,0,1,1,1,0,1,1,0}, 
                {0,1,0,0,0,1,0,0,1,0}, 
                {0,0,1,1,1,1,1,1,1,0}, 
                {0,0,0,0,0,0,0,0,0,0}  
        };
void PrintMaze()
{
    cout<<"the map of maze"<<endl;
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<10;j++)
            cout<<setw(3)<<MazeMap[i][j]<<"  ";
        cout<<endl;
    }
}
void InitStack(Stack&S)
{
    S.base=(ElemType*)malloc(MaxSize* sizeof(ElemType));
    if(!S.base)exit(EOVERFLOW);
    S.top=S.base;
    S.stack_size=MaxSize;
}
void Push(Stack&S,ElemType e)
{
    if(S.top-S.base>=S.stack_size)
        S.base=(ElemType*)malloc((MaxSize+Increment)* sizeof(ElemType));
    if(!S.base)exit(EOVERFLOW);
    *S.top=e;
    S.top++;
}
void Pop(Stack&S,ElemType&e)
{
    if(S.top==S.base)return;
    e=*(--S.top);
}
bool StackEmpty(Stack&S)
{
    return S.base==S.top;
}
void FootPrint(PosType pos,int curstep)
{
    if(pos.row==1&&pos.col==1)			//**********************************************
    {
        MazeMap[pos.row][pos.col]=0;    //*******************改动***********************  
        return;							
    }									//**********************************************
    MazeMap[pos.row][pos.col]=curstep;

}
Status Pass(PosType pos)
{
    if(MazeMap[pos.row][pos.col]==1)return 1;
    return 0;
}
PosType NextPos(PosType CurPos,int i)
{
    switch (i)
    {
        case 1:
            ++CurPos.row;
            break;
        case 2:
            ++CurPos.col;
            break;
        case 3:
            --CurPos.row;
            break;
        case 4:
            --CurPos.col;
            break;
    }
    return CurPos;
}
void MakePrint(PosType pos)
{
    cout<<"("<<pos.row<<","<<pos.col<<") was blocked"<<endl;
    MazeMap[pos.row][pos.col]=0;
}
Status MazePath(PosType start,PosType end)
{
    Stack S;
    PosType curpos;
    ElemType e;
    int curstep;
    InitStack(S);
    curpos=start;
    curstep=1;
    cout<<"begin with: "<<"("<<start.row<<","<<start.col<<")"<<endl;
    do{
        if(Pass(curpos)){
            FootPrint(curpos,curstep);
            cout<<" ->"<<"("<<curpos.row<<","<<curpos.col<<")"<<endl;
            e.ord=curstep;
            e.seat=curpos;
            e.di=1;
            Push(S,e);
            if(curpos.row==end.row&&curpos.col==end.col)
            {
                cout<<"(finished)"<<endl;
                return 1;
            }
            curpos=NextPos(curpos,1);
            curstep++;
            cout<<" step:"<<curstep;
        }
        else
        {
            if(!StackEmpty(S))
            {
                Pop(S,e);
                while(e.di==4&&!StackEmpty(S))
                {
                    MakePrint(e.seat);
                    Pop(S,e);
                    curstep--;
                    cout<<" back to ""("<<e.seat.row<<","<<e.seat.col<<")";
                }
                if(e.di<4)
                {
                    ++e.di;
                    Push(S,e);
                    curpos=NextPos(e.seat,e.di);
                }
            }
        }
    }while(!StackEmpty(S));
    cout<<"no exit"<<endl;
    return 0;
}
int main()
{
    PrintMaze();
    PosType Start,End;
    Start.row=1,Start.col=1;
    End.row=8,End.col=8;
    if(MazePath(Start,End))
    {
        MazeMap[1][1]=1;			//*********************改动*********************
        PrintMaze();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37613112/article/details/88075396