#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <numeric>
#include <functional>
using namespace std;
typedef long long int ll;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<vpll> vvpll;
#define rep(i, a, b) for (ll i = a; i < b; i++)
#define mp(a, b) make_pair(a, b)
#define sz(a) a.size()
#define pb(a) push_back(a)
const ll INF = 1000000000;
vvll wall;
vvll dp;
vvll portal[4]; // for each of the 4 directions, get the distance to the wall...
pll start;
pll cake;
ll R, C;
vvb board;
ll dx[4] = {1, 0, -1, 0};
ll dy[4] = {0, 1, 0, -1};
void calc_wall();
void calc_goal();
void calc_portal();
/*
bool dp_compare(pll a, pll b) {
if (dp[a.first][a.second] == dp[b.first][b.second]) {
return a < b;
}
return dp[a.first][a.second] < dp[b.first][b.second];
}
set<pll, decltype(dp_compare)*> BFS(dp_compare);
*/
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> R >> C;
board.resize(R + 2);
char tmp;
board[0].resize(C + 2);
board[R + 1].resize(C + 2);
rep(j, 0, C + 2) {board[0][j] = false; board[R + 1][j] = false;}
rep(i, 1, R + 1) {
board[i].resize(C + 2);
board[i][0] = false;
board[i][C + 1] = false;
rep(j, 1, C + 1) {
cin >> tmp;
board[i][j] = (tmp != '#');
if (tmp == 'S') {
start = mp(i, j);
}
if (tmp == 'C') {
cake = mp(i, j);
}
}
}
R += 2;
C += 2;
wall.resize(R);
dp.resize(R);
rep(i, 0, 4) portal[i].resize(R);
rep(i, 0, R) {
wall[i].resize(C);
dp[i].resize(C);
rep(j, 0, 4) portal[j][i].resize(C);
rep(j, 0, C) dp[i][j] = INF;
}
// calculate supporting values
calc_wall();
calc_portal();
// do BFS in dp graph...
dp[start.first][start.second] = 0;
/*
rep(i, 0, R) {
rep(j, 0, C) {
if (board[i][j]) BFS.insert(mp(i, j));
}
}
*/
vvpll BFS(R * C, vpll());
vvb vis(R, vb(C, false));
BFS[0].pb(start);
rep(d, 0, R * C) {
for (vpll::iterator cur = BFS[d].begin(); cur != BFS[d].end(); cur++) {
if (vis[cur->first][cur->second]) continue;
vis[cur->first][cur->second] = true;
rep(k, 0, 4) {
// try walking
pll next = mp(cur->first + dx[k], cur->second + dy[k]);
if ((board[next.first][next.second]) && (dp[next.first][next.second] > dp[cur->first][cur->second] + 1)) {
dp[next.first][next.second] = dp[cur->first][cur->second] + 1;
BFS[dp[next.first][next.second]].pb(next);
}
// try shooting
next = mp(cur->first + (dx[k] * portal[k][cur->first][cur->second]), cur->second + (dy[k] * portal[k][cur->first][cur->second]));
if ((portal[k][cur->first][cur->second] >= 1) && (dp[next.first][next.second] > dp[cur->first][cur->second] + wall[cur->first][cur->second])) {
dp[next.first][next.second] = dp[cur->first][cur->second] + wall[cur->first][cur->second];
BFS[dp[next.first][next.second]].pb(next);
}
}
}
BFS[d].clear();
}
cout << dp[cake.first][cake.second] << endl;
return 0;
}
void calc_wall() {
vvb vis(R, vb(C, false));
vpll p, q;
rep(i, 0, R) {
rep(j, 0, C) {
if (!board[i][j]) {
q.pb(mp(i, j));
wall[i][j] = 0;
vis[i][j] = true;
}
}
}
while (!q.empty()) {
for (vpll::iterator itr = q.begin(); itr != q.end(); itr++) {
rep(d, 0, 4) {
pll next = mp(itr->first + dx[d], itr->second + dy[d]);
if ((next.first == -1) || (next.second == -1) || (next.first == R) || (next.second == C)) continue;
if (!vis[next.first][next.second]) {
vis[next.first][next.second] = true;
wall[next.first][next.second] = wall[itr->first][itr->second] + 1;
p.pb(next);
}
}
}
swap(p, q);
p.clear();
}
}
ll portal_dp(ll i, ll j, ll k) {
if (portal[k][i][j] == -2) portal[k][i][j] = portal_dp(i + dx[k], j + dy[k], k) + 1;
return portal[k][i][j];
}
void calc_portal() {
// setup before call dp
rep(i, 0, R) {
rep(j, 0, C) {
rep(k, 0, 4) {
portal[k][i][j] = -1 -(board[i][j]);
}
}
}
rep(i, 0, R) {
rep(j, 0, C) {
rep(k, 0, 4) {
portal_dp(i, j, k);
}
}
}
}
// There is a (RC)^3 dp
// There is also a (RC)^2 dp: if there are 2 portals then one should b-line to one of them
// For each cell we define the following distances:
// Distance to cell before nearest wall
// Distance to goal
// Then from each cell we can do one of 3 operations:
// Move a step up/down/left/right
// Shoot a portal to a wall up/down/left/right and go to nearest wall to appear at where we shot
// Move to goal
// This gives us a 9*RC dp with RC statest and 9 edges per state...
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
0 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
1 ms |
212 KB |
Output is correct |
4 |
Correct |
1 ms |
212 KB |
Output is correct |
5 |
Correct |
1 ms |
340 KB |
Output is correct |
6 |
Correct |
0 ms |
212 KB |
Output is correct |
7 |
Correct |
1 ms |
212 KB |
Output is correct |
8 |
Correct |
0 ms |
212 KB |
Output is correct |
9 |
Correct |
0 ms |
212 KB |
Output is correct |
10 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
0 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
0 ms |
212 KB |
Output is correct |
4 |
Correct |
0 ms |
212 KB |
Output is correct |
5 |
Correct |
0 ms |
340 KB |
Output is correct |
6 |
Correct |
0 ms |
212 KB |
Output is correct |
7 |
Correct |
0 ms |
212 KB |
Output is correct |
8 |
Correct |
0 ms |
212 KB |
Output is correct |
9 |
Correct |
2 ms |
468 KB |
Output is correct |
10 |
Correct |
1 ms |
596 KB |
Output is correct |
11 |
Correct |
1 ms |
468 KB |
Output is correct |
12 |
Correct |
1 ms |
468 KB |
Output is correct |
13 |
Correct |
1 ms |
468 KB |
Output is correct |
14 |
Correct |
1 ms |
212 KB |
Output is correct |
15 |
Correct |
1 ms |
468 KB |
Output is correct |
16 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
0 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
0 ms |
212 KB |
Output is correct |
4 |
Correct |
0 ms |
212 KB |
Output is correct |
5 |
Correct |
9 ms |
3792 KB |
Output is correct |
6 |
Correct |
9 ms |
3792 KB |
Output is correct |
7 |
Correct |
9 ms |
3880 KB |
Output is correct |
8 |
Correct |
7 ms |
4044 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
0 ms |
212 KB |
Output is correct |
4 |
Correct |
1 ms |
212 KB |
Output is correct |
5 |
Correct |
1 ms |
212 KB |
Output is correct |
6 |
Correct |
1 ms |
212 KB |
Output is correct |
7 |
Correct |
1 ms |
212 KB |
Output is correct |
8 |
Correct |
1 ms |
212 KB |
Output is correct |
9 |
Correct |
1 ms |
468 KB |
Output is correct |
10 |
Correct |
1 ms |
596 KB |
Output is correct |
11 |
Correct |
1 ms |
468 KB |
Output is correct |
12 |
Correct |
1 ms |
468 KB |
Output is correct |
13 |
Correct |
1 ms |
468 KB |
Output is correct |
14 |
Correct |
9 ms |
3792 KB |
Output is correct |
15 |
Correct |
9 ms |
3792 KB |
Output is correct |
16 |
Correct |
9 ms |
3868 KB |
Output is correct |
17 |
Correct |
11 ms |
3872 KB |
Output is correct |
18 |
Correct |
9 ms |
3868 KB |
Output is correct |
19 |
Correct |
11 ms |
4052 KB |
Output is correct |
20 |
Correct |
10 ms |
4052 KB |
Output is correct |
21 |
Correct |
10 ms |
3792 KB |
Output is correct |
22 |
Correct |
12 ms |
3800 KB |
Output is correct |
23 |
Correct |
8 ms |
3800 KB |
Output is correct |
24 |
Correct |
9 ms |
4180 KB |
Output is correct |
25 |
Correct |
0 ms |
212 KB |
Output is correct |
26 |
Correct |
1 ms |
468 KB |
Output is correct |
27 |
Correct |
0 ms |
212 KB |
Output is correct |
28 |
Correct |
9 ms |
4124 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
0 ms |
212 KB |
Output is correct |
3 |
Correct |
1 ms |
212 KB |
Output is correct |
4 |
Correct |
0 ms |
212 KB |
Output is correct |
5 |
Correct |
1 ms |
212 KB |
Output is correct |
6 |
Correct |
1 ms |
212 KB |
Output is correct |
7 |
Correct |
1 ms |
212 KB |
Output is correct |
8 |
Correct |
1 ms |
212 KB |
Output is correct |
9 |
Correct |
1 ms |
468 KB |
Output is correct |
10 |
Correct |
1 ms |
468 KB |
Output is correct |
11 |
Correct |
1 ms |
468 KB |
Output is correct |
12 |
Correct |
1 ms |
468 KB |
Output is correct |
13 |
Correct |
1 ms |
468 KB |
Output is correct |
14 |
Correct |
9 ms |
3824 KB |
Output is correct |
15 |
Correct |
9 ms |
3792 KB |
Output is correct |
16 |
Correct |
10 ms |
3788 KB |
Output is correct |
17 |
Correct |
10 ms |
3876 KB |
Output is correct |
18 |
Correct |
10 ms |
3864 KB |
Output is correct |
19 |
Correct |
12 ms |
4052 KB |
Output is correct |
20 |
Correct |
9 ms |
4052 KB |
Output is correct |
21 |
Correct |
9 ms |
3740 KB |
Output is correct |
22 |
Correct |
10 ms |
3740 KB |
Output is correct |
23 |
Correct |
8 ms |
3800 KB |
Output is correct |
24 |
Correct |
217 ms |
84352 KB |
Output is correct |
25 |
Correct |
361 ms |
89068 KB |
Output is correct |
26 |
Correct |
240 ms |
90652 KB |
Output is correct |
27 |
Correct |
273 ms |
90264 KB |
Output is correct |
28 |
Correct |
232 ms |
85900 KB |
Output is correct |
29 |
Correct |
241 ms |
86040 KB |
Output is correct |
30 |
Correct |
257 ms |
85268 KB |
Output is correct |
31 |
Correct |
9 ms |
4180 KB |
Output is correct |
32 |
Correct |
252 ms |
91172 KB |
Output is correct |
33 |
Correct |
0 ms |
212 KB |
Output is correct |
34 |
Correct |
1 ms |
576 KB |
Output is correct |
35 |
Correct |
210 ms |
86332 KB |
Output is correct |
36 |
Correct |
1 ms |
212 KB |
Output is correct |
37 |
Correct |
9 ms |
4172 KB |
Output is correct |
38 |
Correct |
226 ms |
93548 KB |
Output is correct |
39 |
Correct |
191 ms |
81920 KB |
Output is correct |