广度优先搜索解决迷宫问题

依旧是用一个二维数组来存储这个迷宫。最开始的时候小哼在迷宫的(1,1)处,它可以往右走或者往下走。深度优先是一直往右(下)走,直到走不通的时候回到这里。可以使用下面的方法:
通过”一层一层”扩展的方法来找到小哈。扩展的时候发现一个点就将这个点加入到队列中,直到走到小哈的位置(p,q)停下。

用一个结构体实现队列

struct note
{
    int x;//横坐标
    int y;//纵坐标
    int s;//步数
}
struct note que[2501];
int head, tail;
int a[51][51]={0};//用来存储地图
int book[51][51] = {0};//数组book的用处是记录哪些点已经在队列中,防止一个点被重复使用,并全部被初始化0
最先开始的时候需要进行队列的初始化,即将队列设置为空
    head = 1;
    tail = 1;

第一步将(1,1)加入队列,并且标记(1,1)已经走过

que[tail].x = 1;
que[tail].y = 1;
que[tail].s = 0;
tail++;
book[1][1] = 1;

然后从(1,1)开始,先尝试向右到达了(1,2)

tx = que[head].x;
ty = que[head].y+1;
//判断是否越界
if(tx<1 || tx>n || ty<1 || ty>m)
    continue;
//在判断(1,2)是否是障碍物或者已经在路径中
if(a[tx][ty] == 0 && book[tx][ty] == 0)
{

}

若满足上面的条件,则将点入队列,并且标记这个点被使用

    //把这个点标记为已经走过
    book[tx][ty] = 1;
    //插入新的点到队列中
    que[tail].x = tx;
    que[tail].y = ty;
    que[tail].s = que[head].s+1;//步数是父亲步数+1
    tail++;

上面是对一个点的操作,我们走完了这个点,还要继续行走。发现(1,1)还是可以到达(2,1),因此要将(2,1)也加入队列,实现代码如上。
将(1,1)扩展完毕后,(1,1)已经没有用了,此时我们将(1,1)出队。出队的操作如下
head++;
接下来我们需要在刚扩展出来的(1,2)和(2,1)这两个点继续向下探索。
(1,1)出队之后,现在队列的head指向(1,2)这个点,现在将这个点继续扩展,通过(1,2)可以到达(2,2)并且将(2,2)也加入队列。重复这个步骤,直到走到了目标位置。
为了向四个方向扩展,与上一节一样需要一个next数组.

int next[4][2] = {
                {0, 1},//向右走
                {1, 0},//向下走
                {0, -1},//向走左
                {-1, 0}//向上走
            };

全部代码

#include<stdio.h>
struct note
{
    int x;//横坐标
    int y;//纵坐标
    int f;//父亲在队列中的标号
    int s;//步数
};
int main()
{
    struct note que[2501];

    int a[51][51] = {0};
    int book[51][51] = {0};
    //定义一个表示走方向的数组
    int next[4][2] = {{0,1},//向右走
                    {1,0},//向下走
    {0, -1},//向左走
    {-1, 0}};//向上走

    int head, tail;
    int i,j,k,n,m,startx, starty,p,q,tx,ty,flag;

    scanf("%d %d", &n, &m);
    for(i=1; i<=n; i++)
        for(j=1; j<=m;j++)
            scanf("%d", &a[i][j]);
    scanf("%d %d %d %d", &startx, &starty, &p, &q);

    //队列的初始化
    head = 1;
    tail = 1;
    //往队列插入迷宫入口坐标
    que[tail].x = startx;
    que[tail].y = starty;
    que[tail].f = 0;
    que[tail].s = 0;
    tail++;
    book[startx][starty]=1;

    flag=0;//用来标记是否到达目标点,0表示暂时没有到达,1表示到达
    //当队列不为空的时候循环
    while(head<tail)
    {
        //枚举四个方向
        for(k=0; k<=3; k++)
        {
            //计算下一点的坐标
            tx = que[head].x+next[k][0];
            ty = que[head].y+next[k][1];
            //判断是否越界
            for(tx<1 || tx>n || ty<1 || ty>m)
                continue;
            //判断是否障碍物或者已经在路径中
            if(a[tx][ty]==0 && book[tx][ty]==0)
            {
                //将这个点标记为已经走过
                book[tx][ty]=1;
                //插入新的点到队列中
                que[tail].x=tx;
                que[tail].y=ty;
                que[tail].f=head;
                que[tail].s = que[head].s+1;//步数是父亲的步数加1
                tail++;
            }
            //如果到目标点了,停止扩展,任务结束,退出循环
            if(tx==p && ty==q)
            {
                flag = 1;
                break;
            }
        }
        if(flag == 1)
            break;
        head++;//当一个点扩展完之后,才能对下一个点进行扩展
    }
    //打印末尾最后一个点
    printf("%d",que[tail-1].s);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值