洛谷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;
}
posted @ 2025-03-13 20:14  2789617221guo  阅读(47)  评论(0)    收藏  举报