P1825 [USACO11OPEN] Corn Maze S 传送门搜索
解题思路
这道题是一个典型的带传送门的迷宫最短路径问题,需要使用广度优先搜索(BFS)来解决。关键点在于正确处理传送门的逻辑:
-
地图表示:使用二维字符数组存储迷宫,包含起点'@'、终点'='、障碍'#'、草地'.'和传送门'A'-'Z'
-
传送门特性:
-
传送门是双向的,且强制传送(必须使用)
-
传送不消耗时间(步数不变)
-
-
BFS特性:保证第一次到达终点时的步数就是最短路径
-
边界处理:需要检查移动后的坐标是否超出矩阵范围
代码注释
#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; }

浙公网安备 33010602011771号