洛谷P1825 [USACO11OPEN] Corn Maze S 题解
本题做法
- BFS。
思路
本题其实难就难在传送门如何存储。我的做法是使用 3 个 map 存储传送门,一个 map 叫做 \(exist\)(map<char,bool>
),代表传送门 \(c\) 是否存在(就是有没有输入过了),是为了后面的存储判断做准备;第二个 map 叫做 \(lastdoor\)(map<char,pair<int,int>>
),代表传送门 \(c\) 的第一次出现点在哪个位置;最后一个 map 叫做 \(door\)(map<pair<int,int>,pair<int,int>>
),存储的是传送门位置 \((x,y)\) 的另一个对应传送门位置。
读入时,若当前读入的是字符(c>='A'&&c<='Z'
),则判断是否 \(exist[c]\),若真,则做如下操作:
//互相将对应的传送门位置赋值
door[lastdoor[mp[i][j]]]={i,j};
door[{i,j}]=lastdoor[mp[i][j]];
若假,则做如下操作:
//记录已经存在传送门,并记录第一个传送门的位置
exist[mp[i][j]]=1;
lastdoor[mp[i][j]]={i,j};
随后就是愉快的 BFS 模板题了,需要注意的是,我们不能将传送门位置的 \(vis\)(即是否来到过)数组设为 true
,因为我们可能需要多次走一个传送门。
代码
#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const int N = 305;
const int fx[5] = { 0, 0, 1, 0, -1 };
const int fy[5] = { 0, 1, 0, -1, 0 };
#define CHECK(X, Y) \
(X >= 1 && X <= n && Y >= 1 && Y <= m && mp[X][Y] != '#' && !vis[X][Y])
struct coord {
int x;
int y;
int s;
};
int n, m, sx, sy, ex, ey;
char mp[N][N];
bool vis[N][N];
map<pair<int, int>, pair<int, int>> door; // 存储每一个点位对应的另一个传送门
map<char, bool> exist; // 用于在输入时判断这个传送门以前是否有输入过了
map<char, pair<int, int>>
lastdoor; // 用于在输入时存储每个传送门的第一次出现点位
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> mp[i][j];
if (mp[i][j] == '@') {
sx = i;
sy = j;
mp[i][j] = '.';
} else if (mp[i][j] == '=') {
ex = i;
ey = j;
mp[i][j] = '.';
} else if (mp[i][j] >= 'A' && mp[i][j] <= 'Z') {
if (exist[mp[i][j]]) {
door[lastdoor[mp[i][j]]] = { i, j };
door[{ i, j }] = lastdoor[mp[i][j]];
} else {
exist[mp[i][j]] = 1;
lastdoor[mp[i][j]] = { i, j };
}
}
}
}
coord c = { sx, sy, 0 };
vis[sx][sy] = 1;
queue<coord> q;
q.push(c);
while (!q.empty()) {
c = q.front();
q.pop();
int x = c.x, y = c.y, s = c.s;
// cout << "(" << x << "," << y << ")" << endl;
if (x == ex && y == ey) {
cout << s << endl;
return 0;
}
if (door.find({ x, y }) != door.end()) {
pair<int, int> p = door[{ x, y }];
x = p.first;
y = p.second;
}
int tx, ty;
for (int i = 1; i <= 4; i++) {
tx = x + fx[i];
ty = y + fy[i];
if (CHECK(tx, ty)) {
vis[tx][ty] = 1;
q.push({ tx, ty, s + 1 });
}
}
}
return 0;
}