hihocoder #1519 逃离迷宫II

本文介绍了一种解决迷宫问题的高效算法,通过改进BFS搜索策略实现最少转向次数的路径寻找,利用方向数组简化直线行走过程,最终实现快速求解。

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

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi被坏女巫抓进里一间有N x M个格子组成的矩阵迷宫。

有些格子是小Hi可以经过的,我们用’.’表示;有些格子上有障碍物小Hi不能经过,我们用’#’表示。小Hi的起始位置用’S’表示,他需要到达用’T’表示的格子才能逃离迷宫。

麻烦的是小Hi被坏女巫施了魔法,他只能选择上下左右某一个方向,沿着这个方向一直走,直到遇到障碍物或者迷宫边界才能改变方向。新的方向可以是上下左右四个方向之一。之后他还是只能沿着新的方向一直走直到再次遇到障碍物或者迷宫边界……

小Hi想知道他最少改变几次方向才能逃离这个迷宫。
输入

第一行包含两个整数N和M。 (1 <= N, M <= 500)

以下N行每行M个字符,代表迷宫。
输出

一个整数代表答案。如果小Hi没法逃离迷宫,输出-1。
样例输入

5 5
S.#.T  
.....  
.....  
.....  
.....

样例输出

2

  一开始,我想的太复杂了,用BFS逐个扫,一个一个格子走。后来发现代码量太大了,写了半天最后wrong answer。。。于是,一怒之下改了整个程序。下面是主要得思路:
  之前我是一步步走,逐个试,如上样例中,先是(0,0),然后(1,0),(0,1),(2,0),(1,1) ……;后来发现其实不需要,因为在遇到障碍物之前不需要转弯,索性直接让它一路走到黑,遇到障碍再做处理好了。如上样例中,先是(0,0),然后(4,0),(0,1),(4,4),(4,1),(4,0)就到T了。改了程序后,果断AC,下面是AC代码:
  


#include<iostream>
#include<map>
#include<string>
#include<string.h>
#include<queue>
#include<stack>
#include<vector>
#include <cstdio>
#include<fstream>
#include<algorithm>
#include<sstream>
#include<set>
#include<iterator>
using namespace std;

struct node {
    int x;
    int  y;
    int fangx;//1,2,3,4 上左下右
    int step;
    node(int xt=0, int yt=0, int st=0,int fx = 0) :x(xt), y(yt), fangx(fx),step(st) {}
};

int zh[4][2] = { { -1,0 },{0,-1},{1,0},{0,1} };//转换方向用的数组,顺序是上左下右
const  int maxn = 510;
char ditu[maxn][maxn];
bool visit[maxn][maxn];//保存访问的信息
queue<node > duilie;
int M = 0, N = 0;

int walk(node &n,int &flag)//走直线,注意这里是引用,即会改变原来的值
{
    while (ditu[n.x][n.y] != '#'&&n.x<M&&n.y<N&&n.x>-1 && n.y>-1) {//未遇到障碍或者边界
        n.x = n.x+zh[n.fangx][0];
        n.y = n.y+zh[n.fangx][1];
        if (ditu[n.x][n.y] == 'T')//到达T
        {
            flag = 1; //标记为1,表示找到
            break;
        }
    }
    if (!flag) {//未到达T,表示遇到障碍物或边界,此时正在障碍物或边界上,因此需要往原来的方向退一步,才能做转向
        n.x = n.x - zh[n.fangx][0];
        n.y = n.y - zh[n.fangx][1];
    }
    return 0;
}

int LuShi()
{
    int startX = 0, startY = 0, endX = 0, endY = 0;
    memset(visit, false, sizeof(visit));//初始化为false,都为访问
    cin >> M >> N;
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            cin >> ditu[i][j];
            if (ditu[i][j] == 'S') { startX = i, startY = j; }//记录起始位置
        }
    }
    node st(startX, startY, 0);//初始位置的节点,节点位置和转向的步数,此时当然为0
    for (int i = 0; i < 4; i++)
    {
        st.fangx = i;//给初始节点各个方向
        duilie.push(st);//放入队列中
    }
    visit[startX][startY] = true;//初始位置标记访问
    while (!duilie.empty())
    {
        node n = duilie.front();
        int flag = 0;
        duilie.pop();
        walk(n,flag);//让n一路走到黑
        if (flag) {//如果找到了
            cout << n.step << endl;//输出转向的步数
            return 0;
        }
        else
        {
            if (!visit[n.x][n.y]) {//如果走到的位置没有被访问,
                visit[n.x][n.y] = true;//标记访问
                n.step++;//此处需要转向了,因此+1
                int fx = n.fangx;//保存原来的方向
                for (int i = 0; i < 4; i++)
                {
                    if (i != fx) {//确保新的方向不是原方向,因为再走原来的方向是没有意义的
                        n.fangx = i;
                        duilie.push(n);
                    }
                }
            }
        }
    }
    cout << "-1" << endl;//如果一直没有找到,说明不可达
    return 0;
}

int main()
{
    streambuf * inbuf = cin.rdbuf((new ifstream("C:\\Users\\yzc\\Desktop\\input.txt"))->rdbuf());//重定向,OJ时将它注释掉
    //cout << LuShi() << endl;
    LuShi();
    system("pause");
    return 0;
}
### 关于编号为1027的逃离迷宫问题 #### 题目描述 在一个由 `n` 行 `m` 列组成的二维网格中,有一个机器人位于左上角的位置 `(0, 0)`。该机器人的目标是移动到右下角位置 `(n-1, m-1)` 的出口处。每次可以向上、向下、向左或向右移动一步,但不能走出边界。某些格子可能是障碍物,无法通行。 给定一个表示迷宫的地图矩阵 `maze[n][m]`,其中 `0` 表示可以通过的空间,`1` 表示不可通过的墙壁或障碍物。求解是否存在一条路径可以从起点到达终点,并返回这条路径上的坐标序列;如果不存在这样的路径,则输出相应提示信息[^1]。 #### 解决方案概述 为了找到从起始点至终止点的有效路径,可采用广度优先搜索 (BFS) 或者深度优先搜索 (DFS)[^2] 来遍历整个地图空间。这两种方法都是图论中的经典算法,在处理连通性和最短路等问题上有广泛应用价值。对于本题而言: - **初始化**:创建队列并将初始节点加入队列; - **循环条件**:当队列不为空时继续执行; - **扩展状态**:取出当前节点并标记已访问过,尝试沿四个方向探索相邻未被访问过的有效邻居节点; - **结束标志**:一旦触及目的地即刻停止搜索过程,记录成功轨迹;反之则报告失败情况。 ```python from collections import deque def escape_maze(maze): n = len(maze) m = len(maze[0]) # 定义四个可能的方向 directions = [(0, 1), (1, 0), (-1, 0), (0, -1)] queue = deque([((0, 0), [])]) # ((当前位置y,x),(经过的路径)) visited = set([(0, 0)]) while queue: pos, path = queue.popleft() if pos == (n-1, m-1): # 如果已经到了终点 return ["Path found:", *path, "(%d,%d)" % pos] for dy, dx in directions: ny, nx = pos[0]+dy, pos[1]+dx if not (0 <= ny < n and 0 <= nx < m) or maze[ny][nx] != 0 or (ny,nx) in visited: continue new_path = list(path) new_path.append("(%d,%d)"%(pos[0],pos[1])) queue.append(((ny, nx), new_path)) visited.add((ny, nx)) return [&#39;No Path Found&#39;] ``` 此代码实现了上述提到的方法来查找迷宫内的逃生路线。它利用了一个双端队列来进行层次化地逐层展开搜索操作,从而保证最先发现的目标就是距离最近的一条可行径[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值