Quick actions

cmd+k|ctrl+k

Navigation

Languages

Atri

Snippet info

Language

Cpp

Visibility

public

Author

dogdie233

Created

2025-05-19T11:50:45.787089Z

Updated

2025-05-19T16:07:53.583761Z

#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <array>

using namespace std;

size_t hashSeed = 0;

size_t rotl(const size_t value, const int shift) {
    if ((shift &= sizeof(value)*8 - 1) == 0)
      return value;
    return (value << shift) | (value >> (sizeof(value) * 8 - shift));
}

struct Vec2 {
    int x, y;

    Vec2() : x(0), y(0) {}
    Vec2(int x, int y) : x(x), y(y) {}

    // 一种很evil的写法,把vector作为索引,而不是把vector作为索引
    int& operator[](vector<vector<int>>& arr) const {
        return arr[y][x];
    }
    char& operator[](vector<string>& arr) const {
        return arr[y][x];
    }

    bool operator==(const Vec2& other) const {
        return x == other.x && y == other.y;
    }
    bool operator!=(const Vec2& other) const {
        return x != other.x || y != other.y;
    }
    Vec2 operator+(const Vec2& other) const {
        return { x + other.x, y + other.y };
    }
};

template<>
class std::hash<Vec2> {
public:
    size_t operator()(const Vec2& p) const {
        const size_t Prime3 = 3266489917U;
        const size_t Prime4 = 668265263U;

        size_t hash = hashSeed;
        hash = rotl(hash + (size_t)p.x * Prime3, 17) * Prime4;
        hash = rotl(hash + (size_t)p.y * Prime3, 17) * Prime4;
        return hash;
    }
};

int main() {
    hashSeed = time(NULL) + 374761393U;

    int k, w, h;
    Vec2 atori, natsuki;

    cin >> k >> w >> h;
    cin >> atori.x >> atori.y >> natsuki.x >> natsuki.y;
    cin.ignore();
    auto mp = vector<string>(h, string(w, '.'));

    for (auto i = 0; i < h; i++) {
        getline(cin, mp[i]);
    }

    array<array<Vec2, 2>, 10> portals;
    for (auto& p : portals) {
        p[0] = p[1] = Vec2(-1, -1);
    }
    for (auto pos = Vec2(0, 0); pos.y < h; pos.y++) {
        for (pos.x = 0; pos.x < w; pos.x++) {
            if (!isdigit(pos[mp]))
                continue;
            auto idx = pos[mp] - '0';
            (portals[idx][0].x == -1 ? portals[idx][0] : portals[idx][1]) = pos;
        }
    }

    int step = -1;
    auto directions = vector<Vec2>{ {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
    auto visited = vector<vector<int>>(h, vector<int>(w, -1));
    auto nowVisit = unordered_set<Vec2>();
    auto nextVisit = unordered_set<Vec2>{ atori };
    auto postUpdate = unordered_map<Vec2, int>();

    atori[visited] = k;

    while (!nextVisit.empty()) {
        step++;
        nextVisit.swap(nowVisit);
        nextVisit.clear();
        postUpdate.clear();

        for (const auto& pos : nowVisit) {
            if (pos == natsuki) {
                cout << step << endl;
                return 0;
            }
            auto nextK = pos[visited] - 1;
            if (nextK < 0) {
                continue;
            }

            for (auto& dir : directions) {
                auto nextPos = pos + dir;

                if (nextPos.x < 0 || nextPos.x >= w || nextPos.y < 0 || nextPos.y >= h) {
                    continue;
                }
                if (nextPos[visited] >= nextK) {
                    continue;
                }

                auto type = nextPos[mp];
                if (type == '#') {
                    continue;
                }
                else if (type == 'S') {
                    postUpdate[nextPos] = k;
                }
                else if (isdigit(type)) {
                    auto idx = type - '0';
                    auto& portal = portals[idx];
                    auto tpPos = portal[0] == nextPos ? portal[1] : portal[0];
                    if (tpPos[visited] < nextK) {
                        tpPos[visited] = nextK;
                        nextVisit.insert(tpPos);
                    }
                }

                postUpdate[nextPos] = max(postUpdate[nextPos], nextK);
                nextVisit.insert(nextPos);
            }
        }

        for (auto& [pos, newK] : postUpdate) {
            pos[visited] = newK;
        }
    }

    cout << "BE" << endl;
    return 0;
}
INFO