洛谷题单指南-搜索-P1825 [USACO11OPEN] Corn Maze S
原题链接:https://www.luogu.com.cn/problem/P1825
题意解读:计算最短路,依然是BFS。
解题思路:
相比传统的最短路迷宫,多了个传输装置,要解决几个关键问题:
1、传输装置的存储
定义一个数组,vector<node> trans[30],数据的每个元素都是一个vector<node>,里面存两个节点,即一对坐标
2、传输装置的使用
当BFS过程中,如果走到一个字母(即传输装置起点),直接将坐标变换到对应的终点(在trans数组里查找即可)
3、标记已经过的坐标
当对走过的坐标打标记时,注意如果是传输装置,要打在起点上,表示下次不能再走,因为终点是传输过去的,下次如果上下左右经过,是可以再走的。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 305;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};
struct node
{
int x, y;
};
char g[N][N]; //迷宫
bool flag[N][N]; //标记是否已走过
int depth[N][N]; //走过的步数
vector<node> trans[30]; //传送装置,一个字母对应两个坐标
queue<node> q; //队列,用于BFS
int sx, sy; //起点坐标
int n, m;
void bfs(int x, int y)
{
flag[x][y] = true;
q.push({x, y});
while(q.size())
{
node t = q.front(); q.pop();
for(int i = 0; i < 4; i++)
{
int nx = t.x + dx[i], ny = t.y + dy[i];
if(nx < 1 || nx > n || ny < 1 || ny > m) continue;
if(flag[nx][ny] || g[nx][ny] == '#') continue;
flag[nx][ny] = true; //注意标记必须在装置传输起点打上,传输终点没有主动走到过,可以再通过
if(g[nx][ny] >= 'A' && g[nx][ny] <= 'Z') //位于传输装置起点或者终点则需要传输
{
vector<node> pos = trans[g[nx][ny] - 'A'];
if(pos[0].x == nx && pos[0].y == ny)
{
nx = pos[1].x;
ny = pos[1].y;
}
else
{
nx = pos[0].x;
ny = pos[0].y;
}
}
depth[nx][ny] = depth[t.x][t.y] + 1; //步数+1
if(g[nx][ny] == '=') //到达终点
{
cout << depth[nx][ny];
return;
}
q.push({nx, ny});
}
}
}
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] >= 'A' && g[i][j] <= 'Z') trans[g[i][j] - 'A'].push_back({i, j});
}
}
bfs(sx, sy);
return 0;
}