程序设计实习MOOC/第十四周编程作业/B:迷宫问题

本文介绍了一种使用广度优先搜索解决迷宫问题的方法,通过定义一个5x5的二维数组表示迷宫,0表示通路,1表示墙壁。文章详细展示了如何通过广度优先搜索寻找从左上角到右下角的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:B:迷宫问题
总时间限制: 1000ms 内存限制: 65536kB
描述
定义一个二维数组: 
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
输入
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出
左上角到右下角的最短路径,格式如样例所示。
样例输入
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
样例输出
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

解题思路:利用的就是广度优先搜索的方法,从(0,0)开始所有可能的路径都添加到队列中,由于要记录路径,所以队列是用数组实现的,每个状态都应该存储下来,而不能使用queue状态一出队列就没有了;数组通过qHead和qTail实现了队列相同的原理;建立了Node,来存储当前x,y坐标以及其父节点在队列中的位置;加入到队列中的状态就应该立马添加标记。

#include<iostream>
#include<cstring>
using namespace std;

int visited[5][5];//判重标记 
struct Node 
{
    int x;//当前的坐标 
    int y;
    int father;//记录父节点在状态队列中的位置 
    Node(int x, int y, int f):x(x),y(y),father(f){}
    Node(){}
};
Node myQueue[25];//状态队列
int qHead, qTail;//队头指针和队尾指针 

int main()
{
    int a[5][5];//存储迷宫 
    for(int i = 0; i < 5; i++)
        for(int j = 0; j < 5; j++)
            cin >> a[i][j];
     memset(visited, 0, sizeof(visited));//清零 
            
    qHead = 0;
    qTail = 1; 
    myQueue[qHead] = Node(0, 0, -1);//起始节点的父节点标记为-1,添加到队列中(题目保证有解,所以a[0][0]一定是0) 
    visited[0][0] = 1;//添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
    
    while(qHead != qTail)//队列不为空 
    {
        if(myQueue[qHead].x == 4 && myQueue[qHead].y == 4)//找到目标状态
        {
            int i = qHead, route[25], num = 0;
            while(myQueue[i].father != -1)//从后往前找到路径存储下来,直到起始节点为止 
            {
                route[num] = myQueue[i].father;//存储父节点在状态队列的位置 
                i = myQueue[i].father;//指向父节点 
                num++;
            }
            for(int j = num - 1; j >= 0; j--)
            {
                cout << "(" << myQueue[route[j]].x << ", " << myQueue[route[j]].y << ")" <<endl;
            }
            cout << "(4, 4)";//route是从目标节点父节点位置开始存储的,所以最后要记得把目标节点也输出 
            system("pause");
            return 0;//main()中return,程序结束
        }
        //不是目标节点,则扩展当前队头节点 
        
        //尝试上下左右四种移动
        if(a[myQueue[qHead].x - 1][myQueue[qHead].y] == 0 && myQueue[qHead].x >= 1 && !visited[myQueue[qHead].x - 1][myQueue[qHead].y])
        {//能够上移,且节点未被加入队列(未被访问过) 
            myQueue[qTail] = Node(myQueue[qHead].x - 1, myQueue[qHead].y, qHead);// 
            
            //添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
            visited[myQueue[qHead].x - 1][myQueue[qHead].y] = 1;
            qTail++;//队尾指向下一个空的位置 
        }
        if(a[myQueue[qHead].x + 1][myQueue[qHead].y] == 0 && myQueue[qHead].x <= 3 && !visited[myQueue[qHead].x + 1][myQueue[qHead].y])
        {//能够下移,且节点未被加入队列(未被访问过) 
            myQueue[qTail] = Node(myQueue[qHead].x + 1, myQueue[qHead].y, qHead);// 
            
            //添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
            visited[myQueue[qHead].x + 1][myQueue[qHead].y] = 1;
            qTail++;//队尾指向下一个空的位置 
        }
        if(a[myQueue[qHead].x][myQueue[qHead].y - 1] == 0 && myQueue[qHead].y >= 1 && !visited[myQueue[qHead].x][myQueue[qHead].y - 1])
        {//能够左移,且节点未被加入队列(未被访问过) 
            myQueue[qTail] = Node(myQueue[qHead].x, myQueue[qHead].y - 1, qHead);// 
            
            //添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
            visited[myQueue[qHead].x][myQueue[qHead].y - 1] = 1;
            qTail++;//队尾指向下一个空的位置 
        }
        if(a[myQueue[qHead].x][myQueue[qHead].y + 1] == 0 && myQueue[qHead].y <= 3 && !visited[myQueue[qHead].x][myQueue[qHead].y + 1])
        {//能够右移,且节点未被加入队列(未被访问过) 
            myQueue[qTail] = Node(myQueue[qHead].x, myQueue[qHead].y + 1, qHead);// 
            
            //添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
            visited[myQueue[qHead].x][myQueue[qHead].y + 1] = 1;
            qTail++;//队尾指向下一个空的位置 
        }
        
        qHead++;//队头变为下一个元素 
    }
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值