This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// THE CAKE IS A LIE!
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
const int MOD = 1e9+7;
#define F first
#define S second
#define MP make_pair
#define PB push_back
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
const int MXN = 1005;
const int INF = 1e7;
int n, m, si, sj, fi, fj;
string A[MXN];
bool visited[MXN][MXN];
int to_wall[MXN][MXN];
pii go[4][MXN][MXN];
int dist[MXN][MXN];
const int dirI[] = {-1, 1, 0, 0};
const int dirJ[] = {0, 0, -1, 1};
bool in(int i, int j) {
    return i < n && j < m && i >= 0 && j >= 0;
}
int main() {
    cin >> n >> m;
    for(int i = 0; i < n; i++) cin >> A[i];
    for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++) {
        if(A[i][j] == 'S') {
            si = i, sj = j;
        }
        if(A[i][j] == 'C') {
            fi = i, fj = j;
        }
    }
    queue<pii> Q;
    for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) to_wall[i][j] = INF;
    for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++) {
        if(A[i][j] == '#') to_wall[i][j] = 0, Q.push({i, j});
    }
    for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++) {
        if(A[i][j] != '#' && (i == 0 || j == 0 || i == n-1 || j == m-1)) to_wall[i][j] = 1, Q.push({i, j});
    }
    while(!Q.empty()) {
        int i = Q.front().F;
        int j = Q.front().S;
        Q.pop();
        for(int k = 0; k < 4; k++) {
            int ii = i+dirI[k], jj = j+dirJ[k];
            if(!in(ii, jj)) continue;
            if(to_wall[ii][jj] > to_wall[i][j]+1) {
                to_wall[ii][jj] = to_wall[i][j]+1;
                Q.push({ii, jj});
            }
        }
    }
    for(int k = 0; k < 4; k++) {
        int di = dirI[k] == 1 ? -1 : 1;
        int dj = dirJ[k] == 1 ? -1 : 1;
        for(int i = (di == -1 ? n-1 : 0); i != (di == -1 ? -1 : n); i += di) {
            for(int j = (dj == -1 ? m-1 : 0); j != (dj == -1 ? -1 : m); j += dj) {
                int ii = i+dirI[k], jj = j+dirJ[k];
                if(!in(ii, jj) || A[ii][jj] == '#') {
                    go[k][i][j] = {i, j};
                }
                else {
                    go[k][i][j] = go[k][ii][jj];
                }
            }
        }
    }
    for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) dist[i][j] = INF;
    dist[si][sj] = 0;
    priority_queue<pair<int, pii>, vector<pair<int, pii>>, greater<pair<int, pii>>> PQ;
    PQ.push({dist[si][sj], {si, sj}});
    while(!PQ.empty()) {
        int i = PQ.top().S.F;
        int j = PQ.top().S.S;
        PQ.pop();
        // normal movement
        for(int k = 0; k < 4; k++) {
            int ii = i+dirI[k], jj = j+dirJ[k];
            if(!in(ii, jj)) continue;
            if(A[ii][jj] == '#') continue;
            if(dist[ii][jj] > dist[i][j]+1) {
                dist[ii][jj] = dist[i][j]+1;
                PQ.push({dist[ii][jj], {ii, jj}});
            }
        }
        // portal go brrrrrrr
        for(int k = 0; k < 4; k++) {
            int ii = go[k][i][j].F, jj = go[k][i][j].S;
            // too bad this violates unweighted bfs
            if(dist[ii][jj] > dist[i][j]+to_wall[i][j]) {
                dist[ii][jj] = dist[i][j]+to_wall[i][j];
                PQ.push({dist[ii][jj], {ii, jj}});
            }
        }
    }
    cout << dist[fi][fj] << "\n";
    return 0;
}
/*
4 4
.#.C
.#.#
....
S...
*/
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |