제출 #1349330

#제출 시각아이디문제언어결과실행 시간메모리
1349330retardeMaze (JOI23_ho_t3)C++20
94 / 100
2095 ms416584 KiB
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int R, C, N;
    cin >> R >> C >> N;

    int sr, sc, gr, gc;
    cin >> sr >> sc;
    cin >> gr >> gc;
    --sr; --sc; --gr; --gc;

    vector<string> a(R);
    for (int i = 0; i < R; i++) cin >> a[i];

    auto id = [&](int r, int c) {
        return r * C + c;
    };

    int S = id(sr, sc);
    int G = id(gr, gc);

    vector<unsigned char> reached(R * C, 0);
    vector<unsigned char> in_border(R * C, 0);

    vector<int> active;
    active.push_back(S);
    reached[S] = 1;

    int ans = 0;

    while (true) {
        queue<int> q;
        vector<int> touched;
        touched.reserve(active.size());

        for (int v : active) q.push(v);

        while (!q.empty()) {
            int v = q.front();
            q.pop();
            touched.push_back(v);

            if (v == G) {
                cout << ans << '\n';
                return 0;
            }

            int r = v / C;
            int c = v % C;

            if (r > 0) {
                int u = v - C;
                if (!reached[u] && a[r - 1][c] == '.') {
                    reached[u] = 1;
                    q.push(u);
                }
            }
            if (r + 1 < R) {
                int u = v + C;
                if (!reached[u] && a[r + 1][c] == '.') {
                    reached[u] = 1;
                    q.push(u);
                }
            }
            if (c > 0) {
                int u = v - 1;
                if (!reached[u] && a[r][c - 1] == '.') {
                    reached[u] = 1;
                    q.push(u);
                }
            }
            if (c + 1 < C) {
                int u = v + 1;
                if (!reached[u] && a[r][c + 1] == '.') {
                    reached[u] = 1;
                    q.push(u);
                }
            }
        }

        vector<int> border;
        border.reserve(touched.size() * 2);

        for (int v : touched) {
            int r = v / C;
            int c = v % C;

            if (r > 0) {
                int u = v - C;
                if (!reached[u] && a[r - 1][c] == '#' && !in_border[u]) {
                    in_border[u] = 1;
                    border.push_back(u);
                }
            }
            if (r + 1 < R) {
                int u = v + C;
                if (!reached[u] && a[r + 1][c] == '#' && !in_border[u]) {
                    in_border[u] = 1;
                    border.push_back(u);
                }
            }
            if (c > 0) {
                int u = v - 1;
                if (!reached[u] && a[r][c - 1] == '#' && !in_border[u]) {
                    in_border[u] = 1;
                    border.push_back(u);
                }
            }
            if (c + 1 < C) {
                int u = v + 1;
                if (!reached[u] && a[r][c + 1] == '#' && !in_border[u]) {
                    in_border[u] = 1;
                    border.push_back(u);
                }
            }
        }

        for (int v : border) in_border[v] = 0;

        if (border.empty()) {
            cout << -1 << '\n';
            return 0;
        }

        vector<vector<pair<int,int>>> segs(R);
        for (int v : border) {
            int r = v / C;
            int c = v % C;

            int r1 = max(0, r - (N - 1));
            int r2 = min(R - 1, r + (N - 1));
            int c1 = max(0, c - (N - 1));
            int c2 = min(C - 1, c + (N - 1));

            for (int rr = r1; rr <= r2; rr++) {
                segs[rr].push_back({c1, c2});
            }
        }

        vector<int> next_active;
        for (int r = 0; r < R; r++) {
            if (segs[r].empty()) continue;

            sort(segs[r].begin(), segs[r].end());

            int L = segs[r][0].first;
            int Rr = segs[r][0].second;

            auto process_segment = [&](int l, int rr) {
                for (int c = l; c <= rr; c++) {
                    int v = id(r, c);
                    if (reached[v]) continue;
                    reached[v] = 1;
                    next_active.push_back(v);
                }
            };

            for (int i = 1; i < (int)segs[r].size(); i++) {
                if (segs[r][i].first <= Rr + 1) {
                    Rr = max(Rr, segs[r][i].second);
                } else {
                    process_segment(L, Rr);
                    L = segs[r][i].first;
                    Rr = segs[r][i].second;
                }
            }
            process_segment(L, Rr);
        }

        if (next_active.empty()) {
            cout << -1 << '\n';
            return 0;
        }

        active.swap(next_active);
        ans++;
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...