迷宫-广度策略 pta

一个陷入迷宫的老鼠如何找到出口的问题。老鼠希望系统性地尝试所有的路径之后走出迷宫。如果它到达一个死胡同,将原路返回到上一个位置,尝试新的路径。在每个位置上老鼠可以向八个方向运动,顺序是从正东开始按照顺时针进行。无论离出口多远,它总是按照这样的顺序尝试,当到达一个死胡同之后,老鼠将进行“回溯”。迷宫只有一个入口,一个出口,设计程序要求输出迷宫的一条通路。迷宫采用二维存储结构表示,1表示障碍,0表示通路;要求如下: 1、实现队列的相关操作; 2、利用队列进行广度策略搜索算法输出路径;

输入格式:

输入包括三部分: 第一个输入是迷宫大小;第二个输入是迷宫的状态;第三个输入是入口和出口位置

输出格式:

反向输出探索的路径,注意包括入口和出口位置。每个位置之间用分号;分隔。

输入样例:

9
1 1 1 1 1 1 1 1 1
1 0 0 1 1 0 1 1 1
1 1 0 0 0 0 0 0 1
1 0 1 0 0 1 1 1 1
1 0 1 1 1 0 0 1 1
1 1 0 0 1 0 0 0 1
1 0 1 1 0 0 0 1 1
1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1
1 1 7 7

输出样例:

7 7;6 6;5 6;4 5;3 4;2 3;1 2;1 1;

代码

#include <stdio.h>
#include <stdlib.h>
typedef int DataType;
struct Node
{
    DataType data;
    struct Node *link;
};
typedef struct Node*PNode;
struct Queue
{
    PNode f;
    PNode r;
};
typedef struct Queue *LinkQueue;
struct MAZE_STRU
{
    int size;
    int **data;
};
typedef struct MAZE_STRU Maze;
LinkQueue SetNullQueue_Link()//创建空队列
{
    LinkQueue lqueue;
    lqueue=(LinkQueue)malloc(sizeof(struct Queue));
    if(lqueue!=NULL)
    {
        lqueue->f=NULL;
        lqueue->r=NULL;
    }
    else
        printf("Aloc failure!\n");
    return lqueue;
}
int IsNullQueue_Link(LinkQueue lqueue)//判断队列是否为空
{
   return  (lqueue->f==NULL);
}
void EnQueue_Link(LinkQueue lqueue,DataType x)//入队操作
{
    PNode p;
    p=(PNode)malloc(sizeof(struct Node));//申请节点空间
    if(p==NULL)
        printf("Alloc Failure!\n");
    else
    {    p->data=x;//数据域赋值
         p->link=NULL;//指针域赋值
        if(lqueue->f==NULL)//空队列的特殊处理
        {
            lqueue->f=p;
            lqueue->r=p;
        }
        else
        {
            lqueue->r->link=p;//插入队尾
            lqueue->r=p;//修改队尾指针
        }
    }

}
void DeQueue_Link(LinkQueue lqueue)
{
    PNode p;
    if(lqueue->f==NULL)
        printf("It is empty queue!\n");
    else
    {
        p=lqueue->f;
        lqueue->f=lqueue->f->link;
        free(p);
    }
}
DataType FrontQueue_Link(LinkQueue lqueue)
{

    if(lqueue->f==NULL)
    {
         printf("It is empty queue");
         return 0;
    }
    else
    {

        return lqueue->f->data;
    }

}
Maze* InitMaze(int size)
{
    int i;
    Maze*maze=(Maze*)malloc(sizeof(Maze));
    maze->size=size;
    maze->data=(int **)malloc(sizeof(int*)*maze->size);
    for(i=0;i<maze->size;i++)
    {
        maze->data[i]=(int*)malloc(sizeof(int)*maze->size);
    }
    return maze;
}
void ReadMaze(Maze* maze)
{   int i,j;
    for(i=0;i<maze->size;i++)
    {

        for(j=0;j<maze->size;j++)
        scanf("%d",&maze->data[i][j]);
    }
}
void WriteMaze(Maze* maze)
{
    int i,j;
    printf("迷宫的结构如下:\n");
    for(i=0;i<maze->size;i++)
    {
        for(j=0;j<maze->size;j++)
        {
            printf("%5d",maze->data[i][j]);
        }
        printf("\n");
    }
}




int MazeBFS(int entryX,int entryY,int exitX,int exitY,Maze *maze)
{
    LinkQueue linkQueueX=NULL;
    LinkQueue linkQueueY=NULL;
    int direction[8][2]={{0,1},{1,1},{1.0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
    int preposX,preposY;
    int posX,posY;//临时变量,存放坐标点(x,y)

    int i,j,mov;
    int **preposMarkX;//记录迷宫行走的前驱X值
    int **preposMarkY;//记录迷宫行走过程中的前驱Y值
    int **Mark;//标记二维数组,标记那些点走过,不再重复走
    //给存放前驱的数组X分配空间
    preposMarkX=(int **)malloc(sizeof(int*)*maze->size);
    for(i=0;i<maze->size;i++)
    {
        preposMarkX[i]=(int *)malloc(sizeof(int)*maze->size);
    }
    //给存放前驱的数组Y分配空间
    preposMarkY=(int **)malloc(sizeof(int*)*maze->size);
    for(i=0;i<maze->size;i++)
    {
        preposMarkY[i]=(int *)malloc(sizeof(int)*maze->size);
    }//给做标记的二维数组分配空间,并附初值
    Mark=(int **)malloc(sizeof(int*)*maze->size);
    for(i=0;i<maze->size;i++)
    {
        Mark[i]=(int *)malloc(sizeof(int)*maze->size);
    }
    for(i=0;i<maze->size;i++)//给所有元素设置初值
    {
        for(j=0;j<maze->size;j++)
        {
            preposMarkX[i][j]=-1;
            preposMarkX[i][j]=-1;
            Mark[i][j]=0;
        }

    }
    linkQueueX=SetNullQueue_Link();//创建空队列
    linkQueueY=SetNullQueue_Link();//创建空队列
    EnQueue_Link(linkQueueX,entryX);//迷宫入口点入队
    EnQueue_Link(linkQueueY,entryY);//迷宫入口点入队
    Mark[entryX][entryY]=1;//迷宫设置标志位
    while(!IsNullQueue_Link(linkQueueX))
   {
        preposX=FrontQueue_Link(linkQueueX);//取队头
        DeQueue_Link(linkQueueX);//出队
        preposY=FrontQueue_Link(linkQueueY);//取队头
        DeQueue_Link(linkQueueY);//出队
        //将于当前点相邻且满足一定条件的点放入队列
        for(mov=0;mov<8;mov++)
        {
            posX=preposX+direction[mov][0];
            posY=preposY+direction[mov][1];
            if(posX==exitX&&posY==exitY)//到达出口点
            {
                preposMarkX[posX][posY]=preposX;
                preposMarkY[posX][posY]=preposY;
                while(!(posX==entryX&&posY==entryY))
                {
                    preposX=preposMarkX[posX][posY];
                    preposY=preposMarkY[posX][posY];
                    if(posX==exitX&&posY==exitY)
                        printf("%d %d;",exitX,exitY);
                    posX=preposX;
                    posY=preposY;
                    printf("%d %d;",posX,posY);
                }
                return 1;
            }
            //如果能走,且没有被扩展过
            if(maze->data[posX][posY]==0&&Mark[posX][posY]==0)
            {
                EnQueue_Link(linkQueueX,posX);//入队扩展
                EnQueue_Link(linkQueueY,posY);
                Mark[posX][posY]=1;//做标记
                preposMarkX[posX][posY]=preposX;//记录前驱
                preposMarkY[posX][posY]=preposY;
            }

        }
   }
   return 0;
}
int main()
{
    Maze* maze;
    int mazeSize;
    int entryX,entryY,exitX,exitY;
    int find=0;
    scanf("%d",&mazeSize);
    maze=InitMaze(mazeSize);
    ReadMaze(maze);
    scanf("%d%d%d%d",&entryX,&entryY,&exitX,&exitY);
    find=MazeBFS(entryX,entryY,exitX,exitY,maze);
    if(find==0)
        printf("找不到路径!");
    return 0;
}

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值