迷宫求解(使用队列

  在迷宫中,从入口到出口往往有一条或者多条最短路径。可以使用队列来求解迷宫的最短路径,使用队列时,搜索路径是一层一层向前推进,第一次找到出口是搜索的层数最少,这种搜索方法与广度优先算法类似。
  使用队列Qu记录走过的方块,该队列的结构如下:

struct{
    int i;   //方块的行号
    int j;   //方块的列号
    int pre; //前一方块在队列中的下标
}Qu[MaxSize];  //定义顺序队列
int front=0,rear=0; //定义队头和队尾指针并置初值为0

  这里使用的队列Qu不是环形队列,为什么不采用环形队列呢?因为元素出队后,还要利用它输出路径,所以不将出队元素真正地删除。
  搜索从(x1,y1)到(x2,y2)路径的过程是:首先将(x1,y1)入队,在队列Qu不为空时循环,出队一次(由于不是环形队列,该出队元素仍在队列中),称该出队的方块为当前方块,front为该方块在Qu中的下标。
  如果当前方块为出口,则输出路径并结束。否则,按顺时针方向找出当前方块的4个方位中可走的相邻方块(对应的mg数组为0),将这些可能的相邻方块均插入到队列Qu中,其pre设置为搜索路径中上一个方块在Qu中的下标值,也就是当前方块的front值,并将相邻方块对应的mg数组值置为-1,以避免重复搜索。如果队列为空,表示未找到出口,即不存在路径。
  如图(1)所示的迷宫,求它从起点到终点所有的最短路径。
  

迷宫求解(使用队列_第1张图片
  代码如下:
  //migong.cpp  

#include <stdio.h>
#define MaxSize 100
#define M1 6 //迷宫的最大行数
#define N1 6 //迷宫的最大列数
struct{
    int i;   //方块的行号
    int j;   //方块的列号
    int pre; //前一方块在队列中的下标
}Qu[MaxSize];  //定义顺序队列
int front=0,rear=0; //定义队头和队尾指针并置初值为0

int mg1[M1][N1]={  //1: 代表墙,0: 代表通道
    {1,1,1,1,1,1},
    {1,0,0,0,1,1},
    {1,0,1,0,0,1},
    {1,0,0,0,1,1},
    {1,0,0,0,0,1},
    {1,1,1,1,1,1}   
};

int minlen=0;  //最短路径长度
int num=1;   //路径计数

//从队列中输出路径
void print1(int front){
    int k=front,j;
    int ns=0;
    do 
    {
        j=k;
        k=Qu[k].pre;
        ns++;
    } while (k!=-1);
    if(num==1) minlen=ns;
    if (ns==minlen)
    {
        ns=0;
        k=front;
        printf(" 第%d条最短路径(反向输出): \n",num++);
        do 
        {
            j=k;
            printf("\t(%d,%d)",Qu[k].i,Qu[k].j);
            k=Qu[k].pre;
            if(++ns%5 == 0) printf("\n");
        } while (k!=-1);
        printf("\n");
    }
}

//搜索路径为: (x1,y1) --> (x2,y2)
void mgpath1(int x1,int y1,int x2,int y2){
    int i,j,find=0,di,k;
    rear++;
    Qu[rear].i=x1; Qu[rear].j=y1; 
    Qu[rear].pre=-1; //(x1,y1)入队
    while (front <= rear)
    {
        front++;
        for (di=0;di<3;di++)
        {
            switch(di){
            case 0: i=Qu[front].i-1; j=Qu[front].j; 
                break;
            case 1: i=Qu[front].i; j=Qu[front].j+1;
                break;
            case 2: i=Qu[front].i+1; j=Qu[front].j;
                break;
            case 3: i=Qu[front].i; j=Qu[front].j-1;
                break;
            }
            //方块(i,j)不越界,且可走
            if (i>0 && j>0 && mg1[i][j]==0
                &&(i!=Qu[Qu[front].pre].i || j!=Qu[Qu[front].pre].j ))
            {
                rear++;
                Qu[rear].i=i; Qu[rear].j=j;
                Qu[rear].pre=front; //指向路径中上一个方块的下标
            }
        }
    }
    for (k=0;k<=rear;k++)
    {
        if (Qu[k].i==x2 && Qu[k].j==y2) //找到了出口,输出路径
        {
            find=1;
            print1(k);
        }
    }
    if(!find)
        printf("不存在路径!\n");

}

void main()
{
    printf("所有迷宫([1,1]->[4,4])最短路径\n");
    mgpath1(1,1,M1-2,N1-2); //(1,1)->(M1-2,N1-2)
}

效果如下:

迷宫求解(使用队列_第2张图片
图(2) 从起点到终点的最短路径有:4条
  

你可能感兴趣的:(算法,struct,搜索,队列,迷宫)