AcWing 844.走迷宫

844. 走迷宫 - AcWing题库

就是要我们求最短路,可以用bfs。

那么这题目,如果用dfs会有什么情况。

bfs用队列实现,对于为何用队列实现。可以看一下这篇文章【图解算法】BFS 为什么需要 Queue - 知乎 (zhihu.com)

对于 BFS 算法,正如上面所说的,我们需要一层一层遍历所有的相邻结点。那么相邻结点之间的先后顺序如何确定?因此我们需要一个数据结构来进行存储和操作,需要使得先遍历的结点先被存储,直到当前层都被存储后,按照先后顺序,先被存储的结点也会被先取出来,继续遍历它的相邻结点。

因此我们可以发现,这个需求不就是我们的队列吗,First In First Out (FIFO) 完全契合这里的 use case。因此对于 BFS 我们需要使用 Queue 这样的一个数据结构,来存储每一层的结点,同时维护『先进先出 FIFO』的顺序。

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

typedef pair<int,int> PII;//坐标x,y 
const int N=110;
int n,m;
int g[N][N],d[N][N];//g[][]存放迷宫 d[][]存放到起点距离

int bfs()
{
    queue<PII> q;
    
    memset(d,-1,sizeof(d));//距离初始化为-1
    
    d[0][0]=0;//起点 距离为0
    q.push({0,0});//将起点入队列
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//上下左右四个坐标
    while(q.size())//队列不空
    {
        PII t=q.front();//对头取出
        q.pop();//出队头
        
        for(int i=0;i<4;i++)//上下左右检查一下 符合的入队
        {
            int x=t.first+dx[i],y=t.second+dy[i];//x,y是上下左右的坐标
            if(x>=0 && x<n && y>=0 && y<m && g[x][y]==0 && d[x][y]==-1)
            //  x在范围里       y在范围里   0可走 1是墙   这个点未走过,距离为-1
            {
                d[x][y]=d[t.first][t.second]+1;//距离=前一个点的距离+1
                q.push({x,y});//入队
            }
        }
    }
    return d[n-1][m-1];//距离
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin>>g[i][j];//初始化迷宫
            
    cout<<bfs()<<endl;
    return 0;
}

将路径输出,其实就是符合条件的时候,将点放到数组里! 

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

typedef pair<int,int> PII;//坐标x,y 
const int N=110;
int n,m;
int g[N][N],d[N][N];//g[][]存放迷宫 d[][]存放到起点距离
PII pre_v[N][N];

void bfs()
{
    queue<PII> q;
    
    memset(d,-1,sizeof(d));//距离初始化为-1
    
    d[0][0]=0;//起点 距离为0
    q.push({0,0});//将起点入队列
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//上下左右四个坐标
    while(q.size())//队列不空
    {
        PII t=q.front();//对头取出
        q.pop();//出队头
        
        for(int i=0;i<4;i++)//上下左右检查一下 符合的入队
        {
            int x=t.first+dx[i],y=t.second+dy[i];//x,y是上下左右的坐标
            if(x>=0 && x<n && y>=0 && y<m && g[x][y]==0 && d[x][y]==-1)
            //  x在范围里       y在范围里   0可走 1是墙   这个点未走过,距离为-1
            {
                d[x][y]=d[t.first][t.second]+1;//距离=前一个点的距离+1
                q.push({x,y});//入队
                pre_v[x][y]=t;//记录前面的点
            }
        }
    }
    int x=n-1,y=m-1;
    while(x || y)//不为0 0
    {
        cout<<x<<' '<<y<<endl;//输出点
        auto t=pre_v[x][y];//向前一直探
        x=t.first,y=t.second;
    }
    cout<<"0 0"<<endl;//输出起点
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin>>g[i][j];//初始化迷宫
            
    bfs();
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值