제출 #136138

#제출 시각아이디문제언어결과실행 시간메모리
136138Vlatko포탈들 (BOI14_portals)C++14
100 / 100
331 ms42264 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;

const int inf = 1e9;
const int MAXN = 1010;

int dr[4] = {-1, 0, 1, 0};
int dc[4] = {0, 1, 0, -1};
char DCH[4] = {'N', 'E', 'S', 'W'};

struct State {
    int d, r, c;
    State(int dd, int rr, int cc) {
        d = dd, r = rr, c = cc;
    }
    State() {}
    bool operator < (const State &rhs) const {
        return d > rhs.d;
    }
};

int R, C, sr, sc, er, ec;
bool blocked[MAXN][MAXN];
int closest[MAXN][MAXN]; // distance to closest wall
pii wallpos[4][MAXN][MAXN]; // position of wall N/E/S/W of here
int dist[MAXN][MAXN]; // dijkstra
priority_queue<State, vector<State>> pq;

inline bool inside(int r, int c) {
    return r >= 0 && r <= R+1 && c >= 0 && c <= C+1;
}

void getClosest() {
    queue<pii> q;
    for (int r = 0; r <= R+1; ++r) {
        for (int c = 0; c <= C+1; ++c) {
            if (blocked[r][c]) {
                q.emplace(r, c);
                closest[r][c] = 0;
            } else {
                closest[r][c] = -1;
            }
        }
    }
    while (!q.empty()) {
        pii top = q.front();
        q.pop();
        int r = top.first, c = top.second;
        for (int d = 0; d < 4; ++d) {
            int r1 = r + dr[d], c1 = c + dc[d];
            if (closest[r1][c1] == -1) {
                closest[r1][c1] = closest[r][c] + 1;
                q.emplace(r1, c1);
            }
        }
    }
}

void getWallPos() {
    for (int d = 0; d < 4; ++d) {
        int rstart, cstart, rchange, cchange;
        if (dr[d] >= 0) {
            rstart = R, rchange = -1;
        } else { // -1
            rstart = 0, rchange = 1;
        }
        if (dc[d] >= 0) {
            cstart = C, cchange = -1;
        } else {
            cstart = 0, cchange = 1;
        }
        for (int r = rstart; inside(r, 0); r += rchange) {
            for (int c = cstart; inside(0, c); c += cchange) {
                if (!blocked[r][c]) {
                    int r1 = r + dr[d], c1 = c + dc[d];
                    if (blocked[r1][c1]) {
                        wallpos[d][r][c] = {r, c};
                    } else {
                        wallpos[d][r][c] = wallpos[d][r1][c1];
                    }
                }
            }
        }
    }
}

void getDistance() {
    for (int r = 0; r <= R+1; ++r) {
        for (int c = 0; c <= C+1; ++c) {
            dist[r][c] = inf;
        }
    }
    dist[sr][sc] = 0;
    pq.emplace(0, sr, sc);
    while (!pq.empty()) {
        State top = pq.top();
        pq.pop();
        if (top.d > dist[top.r][top.c]) {
            continue;
        }
        // adjacent cells
        for (int d = 0; d < 4; ++d) {
            int r1 = top.r + dr[d], c1 = top.c + dc[d];
            if (inside(r1, c1) && !blocked[r1][c1] && top.d + 1 < dist[r1][c1]) {
                dist[r1][c1] = top.d + 1;
                pq.emplace(top.d + 1, r1, c1);
            }
        }
        // teleport to walls in orthogonal directions
        for (int d = 0; d < 4; ++d) {
            pii target = wallpos[d][top.r][top.c];
            int tr = target.first, tc = target.second;
            int newdist = top.d + closest[top.r][top.c];
            if (newdist < dist[tr][tc]) {
                dist[tr][tc] = newdist;
                pq.emplace(newdist, tr, tc);
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> R >> C;
    for (int r = 0; r <= R+1; ++r) {
        blocked[r][0] = blocked[r][C+1] = 1;
    }
    for (int c = 0; c <= C+1; ++c) {
        blocked[0][c] = blocked[R+1][c] = 1;
    }
    for (int r = 1; r <= R; ++r) {
        for (int c = 1; c <= C; ++c) {
            char ch;
            cin >> ch;
            if (ch == 'S') {
                sr = r, sc = c;
            } else if (ch == 'C') {
                er = r, ec = c;
            }
            blocked[r][c] = (ch == '#');
        }
    }
    getClosest();
    getWallPos();
    getDistance();
    cout << dist[er][ec] << '\n';
}
#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...