P1825 [USACO11OPEN] Corn Maze S 传送门搜索

解题思路

这道题是一个典型的带传送门的迷宫最短路径问题,需要使用广度优先搜索(BFS)来解决。关键点在于正确处理传送门的逻辑:

  1. 地图表示:使用二维字符数组存储迷宫,包含起点'@'、终点'='、障碍'#'、草地'.'和传送门'A'-'Z'

  2. 传送门特性:

    • 传送门是双向的,且强制传送(必须使用)

    • 传送不消耗时间(步数不变)

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

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

代码注释

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

const int N = 1e3 + 10;  // 定义足够大的矩阵尺寸

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

char g[N][N];     // 存储地图的二维数组
int n, m;         // 地图的行数和列数
int sx, sy, ex, ey; // 起点(@)和终点(=)的坐标
int vis[N][N];    // 访问标记数组,记录是否已经访问过
int nex[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};  // 四个移动方向:右、下、左、上

// 处理传送门函数:找到当前传送门对应的另一端
void solve(int &x, int &y) {
    // 遍历整个地图寻找相同字母的另一个位置
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            if(g[i][j] == g[x][y] && (i != x || j != y)) {  // 找到相同字母但不是自身的位置
                x = i, y = j;  // 更新坐标为传送门另一端
                return;
            }
}

// BFS函数,从起点(sx,sy)开始搜索
void bfs(int sx, int sy) {
    queue<node> q;       // 创建队列用于BFS
    vis[sx][sy] = 1;     // 标记起点已访问
    q.push({sx, sy, 0}); // 起点入队,初始步数为0
    
    while(q.size()) {    // 当队列不为空时循环
        node h = q.front(); q.pop(); // 取出队首元素
        
        // 如果当前位置是传送门,处理传送
        if(g[h.x][h.y] >= 'A' && g[h.x][h.y] <= 'Z') 
            solve(h.x, h.y);  // 传送到另一端
        
        // 尝试四个方向移动
        for(int i = 0; i < 4; i++) {
            int tx = h.x + nex[i][0];  // 计算新坐标x
            int ty = h.y + nex[i][1];  // 计算新坐标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;              // 直接返回
            }
        }
    }
}

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] == '@') sx = i, sy = j;  // 记录起点坐标
            if(g[i][j] == '=') ex = i, ey = j;  // 记录终点坐标
        } 
    
    // 执行BFS搜索
    bfs(sx, sy);
    
    return 0;
}

 

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