제출 #1356161

#제출 시각아이디문제언어결과실행 시간메모리
1356161nathako9nPortals (BOI14_portals)C++20
100 / 100
142 ms25356 KiB
#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;

const int N = 1005;
char ar[N+3][N+3];
int n, m;
ll dp[N+3][N+3];
int px[] = {-1, 0, 1, 0}, py[] = {0, 1, 0, -1};
int up[N+3][N+3], dow[N+3][N+3], lef[N+3][N+3], rig[N+3][N+3];

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    if (!(cin >> n >> m)) return 0;
    int sx, sy, ex, ey;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> ar[i][j];
            if (ar[i][j] == 'S') { sx = i; sy = j; }
            else if (ar[i][j] == 'C') { ex = i; ey = j; }
            dp[i][j] = 1e18;
        }
    }

    // Precompute the row/column of the open square adjacent to the first wall in each direction
    for (int i = 1; i <= n; i++) {
        int last = 0; // Virtual wall at boundary
        for (int j = 1; j <= m; j++) {
            if (ar[i][j] == '#') last = j;
            lef[i][j] = last + 1;
        }
        last = m + 1; // Virtual wall at boundary
        for (int j = m; j >= 1; j--) {
            if (ar[i][j] == '#') last = j;
            rig[i][j] = last - 1;
        }
    }
    for (int j = 1; j <= m; j++) {
        int last = 0;
        for (int i = 1; i <= n; i++) {
            if (ar[i][j] == '#') last = i;
            up[i][j] = last + 1;
        }
        last = n + 1;
        for (int i = n; i >= 1; i--) {
            if (ar[i][j] == '#') last = i;
            dow[i][j] = last - 1;
        }
    }

    priority_queue<tuple<ll, int, int>, vector<tuple<ll, int, int>>, greater<tuple<ll, int, int>>> pq;
    dp[sx][sy] = 0;
    pq.push({0, sx, sy});

    while (!pq.empty()) {
        auto [w, cx, cy] = pq.top(); pq.pop();
        if (w > dp[cx][cy]) continue;

        // 1. Calculate distance to the NEAREST wall to determine teleport entry cost
        // Distance is (current_pos - wall_adjacent_pos)
        int d_up = cx - up[cx][cy];
        int d_down = dow[cx][cy] - cx;
        int d_left = cy - lef[cx][cy];
        int d_right = rig[cx][cy] - cy;
        int min_d = min({d_up, d_down, d_left, d_right});
        
        // Total cost to teleport: walk to nearest wall (min_d) + teleport move (1)
        ll teleport_total_cost = w + min_d + 1;

        // 2. Try teleporting to the 4 possible cardinal wall locations
        auto try_node = [&](int nx, int ny, ll cost) {
            if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && ar[nx][ny] != '#' && dp[nx][ny] > cost) {
                dp[nx][ny] = cost;
                pq.push({dp[nx][ny], nx, ny});
            }
        };

        try_node(up[cx][cy], cy, teleport_total_cost);
        try_node(dow[cx][cy], cy, teleport_total_cost);
        try_node(cx, lef[cx][cy], teleport_total_cost);
        try_node(cx, rig[cx][cy], teleport_total_cost);

        // 3. Try standard adjacent movement (cost 1)
        for (int i = 0; i < 4; i++) {
            try_node(cx + px[i], cy + py[i], w + 1);
        }
    }

    cout << dp[ex][ey] << endl;
    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...