HNCU1742:算法3-3:迷宫

http://hncu.acmclub.com/index.php?app=problem_title&id=111&problem_id=1742

题目描述

有一个 10 x 10 的迷宫,起点是‘S’,终点是‘E’,墙是‘#’,道路是空格。一个机器人从起点走到终点。当机器人走到一个通道块,前面已经没有路可走时,它会转向到当前面向的右手方向继续走。如果机器人能够过,则留下足迹‘*’,如果走不通,则留下标记‘!’。
下面给出书中的算法,请你模拟机器人的走法输出最终的状态。
图:迷宫算法

输入格式

一个 10 x 10 的二维字符数组。

输出

机器人走过的路径状态。

样例输入

##########
#S #   # #
#  #   # #
#    ##  #
# ###    #
#   #    #
# #   #  #
# ### ## #
##      E#
##########

样例输出

##########
#**#!!!# #
# *#!!!# #
#**!!##  #
#*###    #
#***#    #
# #***#  #
# ###*## #
##   ****#
##########

 

#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW 0
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */

#define MAXLENGTH 25 /* 设迷宫的最大行列为25 */
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
typedef struct
{
    int r, c;                // 以行号和列号作为“坐标位置”类型
} PosType;

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

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

typedef struct
{
    char arr[10][11];
} MazeType;       // 定义迷宫类型(二维字符数组)


/* 定义墙元素值为0,可通过路径为1,不能通过路径为-1,通过路径为足迹 */

Status Pass(MazeType MyMaze, PosType CurPos)
{
    if (MyMaze.arr[CurPos.r][CurPos.c]==' ' || MyMaze.arr[CurPos.r][CurPos.c]=='S' || MyMaze.arr[CurPos.r][CurPos.c]=='E')
        return 1; // 如果当前位置是可以通过,返回1
    else
        return 0; // 其它情况返回0
}

void FootPrint(MazeType &MyMaze, PosType CurPos)
{
    MyMaze.arr[CurPos.r][CurPos.c] = '*';
}

PosType NextPos(PosType CurPos, int Dir)
{
    PosType ReturnPos;
    switch (Dir)
    {
    case 1:
        ReturnPos.r = CurPos.r;
        ReturnPos.c = CurPos.c + 1;
        break;
    case 2:
        ReturnPos.r = CurPos.r + 1;
        ReturnPos.c = CurPos.c;
        break;
    case 3:
        ReturnPos.r = CurPos.r;
        ReturnPos.c = CurPos.c - 1;
        break;
    case 4:
        ReturnPos.r = CurPos.r - 1;
        ReturnPos.c = CurPos.c;
        break;
    }
    return ReturnPos;
}
void MarkPrint(MazeType &MyMaze, PosType CurPos)
{
    MyMaze.arr[CurPos.r][CurPos.c] = '!';
}

Status InitStack(SqStack *S)
{
    /* 构造一个空栈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)
{
    /* 插入元素e为新的栈顶元素 */
    if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
    {
        (*S).base=(SElemType *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));
        if(!(*S).base)
            exit(OVERFLOW); /* 存储分配失败 */
        (*S).top=(*S).base+(*S).stacksize;
        (*S).stacksize+=STACKINCREMENT;
    }
    *((*S).top)++=e;
    return OK;
}

Status StackEmpty(SqStack S)
{
    /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
    if(S.top==S.base)
        return TRUE;
    else
        return FALSE;
}

Status Pop(SqStack *S,SElemType *e)
{
    /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
    if((*S).top==(*S).base)
        return ERROR;
    *e=*--(*S).top;
    return OK;
}

Status MazePath(MazeType &maze, PosType start, PosType end)
{
    // 算法3.3
    // 若迷宫maze中从入口 start到出口 end的通道,则求得一条存放在栈中
    // (从栈底到栈顶),并返回TRUE;否则返回FALSE
    SqStack S;
    PosType curpos;
    int curstep;
    SElemType e;
    InitStack(&S);
    curpos = start; // 设定"当前位置"为"入口位置"
    curstep = 1; // 探索第一步
    do
    {
        if (Pass(maze, curpos))   // 当前位置可通过,即是未曾走到过的通道块
        {
            FootPrint(maze, curpos); // 留下足迹
            e.di = 1;
            e.ord = curstep;
            e.seat = curpos;
            Push(&S, e); // 加入路径
            if (curpos.r == end.r && curpos.c == end.c)
                return (TRUE); // 到达终点(出口)
            curpos = NextPos(curpos, 1); // 下一位置是当前位置的东邻
            curstep++; // 探索下一步
        }
        else     // 当前位置不能通过
        {
            if (!StackEmpty(S))
            {
                Pop(&S, &e);
                while (e.di == 4 && !StackEmpty(S))
                {
                    MarkPrint(maze, e.seat);
                    Pop(&S, &e); // 留下不能通过的标记,并退回一步
                } // while
                if (e.di < 4)
                {
                    e.di++;
                    Push(&S, e); // 换下一个方向探索
                    curpos = NextPos(e.seat, e.di); // 当前位置设为新方向的相邻块
                } // if
            } // if
        } // else
    }
    while (!StackEmpty(S));
    return FALSE;
} // MazePath

int main()
{
    int i, j;
    PosType start, end;                                                // 起点终点坐标
    MazeType maze;                                                        // 迷宫
    memset(maze.arr, 0, sizeof(maze.arr)); // 将字符串设置为空
    for(i=0; i<10; i++) // 读取迷宫数据
    {
        gets(maze.arr[i]);
        for(j=0; j<10; j++)
        {
            if(maze.arr[i][j] == 'S') // 获得起点坐标
            {
                start.r = i;
                start.c = j;
            }
            else if(maze.arr[i][j] == 'E')  // 获得终点坐标
            {
                end.r = i;
                end.c = j;
            }
        }
    }
    MazePath(maze, start, end); // 移动
    for(i=0; i<10; i++) // 输出状态
    {
        puts(maze.arr[i]);
    }

    return 0;
}


 

你可能感兴趣的:(ACM,HNCU)