【刷题·队列】迷宫中离入口最近的出口

文章讲述了如何使用C++实现算法解决LeetCode题目1926,即在迷宫中找到从入口到最近出口的最短路径。作者提到关键在于正确处理边界条件并用队列遍历邻居节点,同时提供了两种不同版本的代码,一种不显示路径,另一种可以打印路径。
摘要由CSDN通过智能技术生成

前言

一开始虽然知道将已经访问过的格子设置为墙,但是没有完全弄清楚是在哪里设置。其实在遍历周围4个点的时候,只要它不是边界空格子,就可以把它设置为墙。我就是在这里超时了。对照着官方题解才找到原因。

代码

实现了2个版本,一个比较简洁,一个可以打印路径

/*
 * @lc app=leetcode.cn id=1926 lang=cpp
 *
 * [1926] 迷宫中离入口最近的出口
 */

// @lc code=start

#include<vector>
#include<tuple>
#include<queue>
using namespace std;
#include<iostream>

struct HWPos
{
    int h;
    int w;

    HWPos* father;
};

class Solution {
public:
    int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) 
    {
        #if 0 //不显示路径的做法
        int rows = maze.size();
        int cols = maze[0].size();

        queue<tuple<int,int,int>> q; // [h,w], step

        q.emplace(entrance[0],entrance[1],0);
        //maze[entrance[0]][entrance[1]] = '+'; 

        int a[4] = {1,-1,0,0};
        int b[4] = {0, 0,-1,1};

        while(q.empty() == false)
        {
            //int h, w, d;
            auto [h,w,d] = q.front();
            q.pop();
            // 是否是终点
            if(h==0 || h==rows-1 || w==0 || w==cols-1)
            {
                if(d > 0) return d;
            }
            // 置为墙
            maze[h][w] = '+';

            //
            for(int i=0 ;i<4; ++i)
            {
                int newh = h + a[i];
                int neww = w + b[i];
                // 是否合法
                if(newh>=0 && newh < rows && neww>=0 && neww < cols && maze[newh][neww]!='+')
                {
                    if(newh==0 || newh==rows-1 || neww==0 || neww==cols-1)
                    {
                        return d+1;
                    }
                    else
                    {
                        q.emplace(newh,neww, d+1);
                        maze[newh][neww] = '+';
                    }
                }
            }            
        }

        return -1;
        #endif


        #if 1 //显示路径的做法
        int rows = maze.size();
        int cols = maze[0].size();

        queue<HWPos*> q;
        HWPos* start = new HWPos;
        start->h = entrance[0]; start->w = entrance[1];
        start->father = nullptr;

        maze[entrance[0]][entrance[1]] = '+';
        q.emplace(start);

        HWPos* end = new HWPos; bool findend = false;

        while(q.empty()==false)
        {
            HWPos* curPos = q.front();
            q.pop();

            int dh[4]{-1,1,0,0};
            int dw[4]{0,0,1,-1};

            for(int i=0; i<4; ++i)
            {
                int newh = curPos->h + dh[i];
                int neww = curPos->w + dw[i];
                // 判断是否合法
                if(newh>=0 && newh<rows && neww>=0 && neww<cols && maze[newh][neww]!='+')
                {
                    HWPos* newpos = new HWPos;
                    newpos->father = curPos;
                    newpos->h = newh; newpos->w = neww;

                    if(newh==0 || newh==rows-1 || neww==0 || neww==cols-1)
                    {
                        findend = true;
                        end->father = curPos;
                        end->h = newh; end->w = neww;
                        
                        delete newpos;
                        break;
                    }
                    else
                    {
                        // 普通白格子
                        maze[newh][neww] = '+';
                        q.push(newpos);
                    }
                }
            }
            if(findend==true) break;
        }

        if(findend==true)
        {
            int step = 0;
            cout<<"end to start path: "<<endl;
            cout<<"["<<end->h<<","<<end->w<<"]<-";

            while(end->father!=nullptr)
            {
                HWPos * tmp = end; // 先让end指向别的地方

                end = end->father;

                if(end->father!=nullptr)cout<<"["<<end->h<<","<<end->w<<"]<-";
                else cout<<"["<<end->h<<","<<end->w<<"]"<<endl;
                

                delete tmp; // 释放之前的end指向的地方

                step +=1;
            } 
            // 说明已经到了start            
            delete end;           

            return step;
        }
        return -1;
        #endif
    }
};
// @lc code=end
Accepted
194/194 cases passed (104 ms)
Your runtime beats 72.23 % of cpp submissions
Your memory usage beats 26.35 % of cpp submissions (33.1 MB)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值