P2298 Mzc和男家丁的游戏 标准广搜模板

解题思路

这道题是一个典型的二维矩阵中的最短路径问题,可以使用广度优先搜索(BFS)来解决。BFS非常适合解决这种无权图的最短路径问题,因为它会逐层扩展搜索,第一次到达目标点时经历的步数就是最短路径。

关键点:

  1. 矩阵表示:用二维字符数组g存储地图,包含起点'm'、终点'd'、障碍'#'和空地'.'

  2. BFS特性:BFS保证第一次到达终点时的步数就是最短路径

  3. 边界处理:需要检查移动后的坐标是否超出矩阵范围

  4. 访问标记:使用vis数组避免重复访问和陷入循环

代码注释

#include<bits/stdc++.h>
using namespace std;

const int N = 2e3 + 10;  // 定义矩阵最大尺寸

// 定义节点结构体,存储坐标和步数
struct node {
    int x, y, step;  // x,y是坐标,step是到达该点的步数
};

char g[N][N];     // 存储地图的二维数组
int vis[N][N];    // 访问标记数组,记录是否已经访问过
int n, m;         // 地图的行数和列数
int sx, sy, ex, ey; // 起点(m)和终点(d)的坐标

// 四个移动方向:右、下、左、上
int nex[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};

// BFS函数,从起点(sx,sy)开始搜索
void bfs(int sx, int sy) {
    queue<node> q;       // 创建队列用于BFS
    q.push({sx, sy, 0}); // 起点入队,初始步数为0
    vis[sx][sy] = 1;     // 标记起点已访问
    
    while(q.size()) {    // 当队列不为空时循环
        node h = q.front(); q.pop(); // 取出队首元素
        
        // 尝试四个方向移动
        for(int i = 0; i < 4; i++) {
            int tx = nex[i][0] + h.x;  // 计算新坐标x
            int ty = nex[i][1] + h.y;  // 计算新坐标y
            
            // 边界检查:超出矩阵范围则跳过
            if(tx < 1 || ty < 1 || tx > n || ty > m) continue;
            
            // 检查是否是障碍或已访问过
            if(g[tx][ty] == '#' || vis[tx][ty]) continue;
            
            vis[tx][ty] = 1;  // 标记为已访问
            q.push({tx, ty, h.step + 1});  // 新位置入队,步数+1
            
            // 如果到达终点
            if(tx == ex && ty == ey) {
                cout << h.step + 1;  // 输出当前步数
                return;              // 直接返回
            }
        }
    }
    
    // 如果队列为空仍未找到终点,输出无解
    cout << "No Way!";
}

int main() {
    // 读取输入
    cin >> n >> m;
    
    // 读取地图数据
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            cin >> g[i][j];
            if(g[i][j] == 'm') sx = i, sy = j;  // 记录起点坐标
            if(g[i][j] == 'd') ex = i, ey = j;  // 记录终点坐标
        }
    
    // 执行BFS搜索
    bfs(sx, sy);
    
    return 0;
}

算法分析

  1. 时间复杂度:O(n×m),最坏情况下需要遍历整个矩阵

  2. 空间复杂度:O(n×m),用于存储访问标记和队列

  3. 优化考虑:

    • 可以使用双向BFS进一步优化性能

    • 对于大型矩阵,可以考虑使用更高效的数据结构

    • 提前终止条件:找到终点立即返回

注意事项

  1. 题目中矩阵的行列索引从1开始

  2. 题目要求1秒内完成,对于2000×2000的矩阵,常规BFS在C++中是可以接受的

  3. 障碍物'#'和访问标记vis都需要检查,避免重复计算

posted @ 2025-06-06 12:39  CRt0729  阅读(14)  评论(0)    收藏  举报