Submission #6921

#TimeUsernameProblemLanguageResultExecution timeMemory
6921tncks0121Portals (BOI14_portals)C++98
100 / 100
368 ms31372 KiB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#include <assert.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <string>
#include <functional>
#include <vector>
#include <deque>
#include <utility>
#include <bitset>
#include <limits.h>

using namespace std;
typedef long long ll;
typedef unsigned long long llu;
typedef double lf;
typedef unsigned int uint;
typedef long double llf;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;

const int SZ = 1005;

const int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};

int R, C;
char D[SZ][SZ];

queue<int> que;
void ins (int x, int y) {
    que.push(x);
    que.push(y);
}

int dist_wall[SZ][SZ];
int where_portal[4][SZ][SZ];

struct state {
    int x, y, d;
    state (int x = 0, int y = 0, int d = 0): x(x), y(y), d(d) { }
    bool operator < (const state &s) const { return d < s.d; }
    bool operator > (const state &s) const { return d > s.d; }
};

priority_queue<state, vector<state>, greater<state> > PQ;
int dst[SZ][SZ];

int main() {
    scanf("%d%d", &R, &C);
    for(int i = 1; i <= R; i++) scanf("%s", D[i]+1);
    
    // step 1: 각 격자에서 벽까지의 거리 구하기
    for(int i = 1; i <= R; i++) ins(i, 0), ins(i, C+1), D[i][0] = D[i][C+1] = '#';
    for(int j = 1; j <= C; j++) ins(0, j), ins(R+1, j), D[0][j] = D[R+1][j] = '#';
    for(int i = 1; i <= R; i++) for(int j = 1; j <= C; j++) {
        dst[i][j] = (int)1e6;
        if(D[i][j] == '#') que.push(i), que.push(j);
        if(D[i][j] == 'S') PQ.push( state(i, j, 0) ), dst[i][j] = 0;
    }
    
    while(!que.empty()) {
        int x = que.front(); que.pop();
        int y = que.front(); que.pop();
        for(int d = 0; d < 4; d++) {
            int xx = x+dx[d], yy = y+dy[d];
            if(D[xx][yy] == '#') continue;
            if(xx < 1 || yy < 1 || xx > R || yy > C || dist_wall[xx][yy] > 0) continue;
            dist_wall[xx][yy] = dist_wall[x][y] + 1;
            que.push(xx); que.push(yy);
        }
    }
    
    // step 2: 각 격자에서 위, 아래, 오른쪽, 왼쪽으로 포탈 쏘았을 때 닿는 벽 구하기
    for(int i = 1; i <= R; i++) {
        for(int j = 1; j <= C; j++) {
            where_portal[0][i][j] = (D[i-1][j] == '#') ? i : where_portal[0][i-1][j];
            where_portal[2][i][j] = (D[i][j-1] == '#') ? j : where_portal[2][i][j-1];
        }
    }
    for(int i = R; i > 0; i--) {
        for(int j = C; j > 0; j--) {
            where_portal[1][i][j] = (D[i+1][j] == '#') ? i : where_portal[1][i+1][j];
            where_portal[3][i][j] = (D[i][j+1] == '#') ? j : where_portal[3][i][j+1];
        }
    }
    
    // step 3: dijkstra
    while(!PQ.empty()) {
        state s = PQ.top(); PQ.pop();
        if(s.d > dst[s.x][s.y]) continue;
        if(D[s.x][s.y] == 'C') {
            printf("%d\n", s.d);
            return 0;
        }
        for(int d = 0; d < 4; d++) {
            state nxt = state(s.x + dx[d], s.y + dy[d], s.d + 1);
            if(D[nxt.x][nxt.y] == '#') continue;
            if(nxt.x < 1 || nxt.y < 1 || nxt.x > R || nxt.y > C) continue;
            if(dst[nxt.x][nxt.y] > nxt.d) {
                dst[nxt.x][nxt.y] = nxt.d;
                PQ.push (nxt);
            }
        }
        for(int d = 0; d < 4; d++) {
            state nxt = (d < 2) ?
                state(where_portal[d][s.x][s.y], s.y, s.d + dist_wall[s.x][s.y])
                : state(s.x, where_portal[d][s.x][s.y], s.d + dist_wall[s.x][s.y]);
            if(D[nxt.x][nxt.y] == '#') continue;
            if(nxt.x < 1 || nxt.y < 1 || nxt.x > R || nxt.y > C) continue;
            if(dst[nxt.x][nxt.y] > nxt.d) {
                dst[nxt.x][nxt.y] = nxt.d;
                PQ.push (nxt);
            }
        }
    }
    
    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...