Codeforces Round #354 Div2 D: Theseus and labyrinth
解法
筋肉ダイクストラ
コード
#include <bits/stdc++.h> using namespace std; template <class T, class U> void chmin(T &t, U f) { if (t > f) t = f; } typedef tuple<int, int, int, int> P; // dist, layer, h,w const int INF = 1e9, LAYERS = 4; const int RIGHT = 0, LEFT = 1, DOWN = 2, UP = 3; const string US = "+|^LRD"; const string DS = "+|vLRU"; const string LS = "+-<RUD"; const string RS = "+->UDL"; const int DH[] = {0, 0, 1, -1}; const int DW[] = {1, -1, 0, 0}; int H, W; char getlayerblock(char c, int layer) { if (layer == 0) return c; switch (c) { case '+': return '+'; case '*': return '*'; case '-': if (layer == 2) return '-'; return '|'; case '|': if (layer == 2) return '|'; return '-'; case '^': if (layer == 1) return '>'; if (layer == 2) return 'v'; if (layer == 3) return '<'; case '>': if (layer == 1) return 'v'; if (layer == 2) return '<'; if (layer == 3) return '^'; case 'v': if (layer == 1) return '<'; if (layer == 2) return '^'; if (layer == 3) return '>'; case '<': if (layer == 1) return '^'; if (layer == 2) return '>'; if (layer == 3) return 'v'; case 'R': if (layer == 1) return 'D'; if (layer == 2) return 'L'; if (layer == 3) return 'U'; case 'D': if (layer == 1) return 'L'; if (layer == 2) return 'U'; if (layer == 3) return 'R'; case 'L': if (layer == 1) return 'U'; if (layer == 2) return 'R'; if (layer == 3) return 'D'; case 'U': if (layer == 1) return 'R'; if (layer == 2) return 'D'; if (layer == 3) return 'L'; default: break; } assert(false); return c; } bool cango(const vector<string> &maze, int layer, int h, int w, int dir) { int nh = h + DH[dir]; int nw = w + DW[dir]; if (nh < 0 || nh >= H) return false; if (nw < 0 || nw >= W) return false; char now = getlayerblock(maze[h][w], layer); char next = getlayerblock(maze[nh][nw], layer); if (dir == UP) { bool ok1 = false, ok2 = false; for (char c : US) if (c == now) ok1 = true; for (char c : DS) if (c == next) ok2 = true; if (ok1 && ok2) return true; return false; } if (dir == DOWN) { bool ok1 = false, ok2 = false; for (char c : DS) if (c == now) ok1 = true; for (char c : US) if (c == next) ok2 = true; if (ok1 && ok2) return true; return false; } if (dir == RIGHT) { bool ok1 = false, ok2 = false; for (char c : RS) if (c == now) ok1 = true; for (char c : LS) if (c == next) ok2 = true; if (ok1 && ok2) return true; return false; } if (dir == LEFT) { bool ok1 = false, ok2 = false; for (char c : LS) if (c == now) ok1 = true; for (char c : RS) if (c == next) ok2 = true; if (ok1 && ok2) return true; return false; } assert(false); return false; } int main() { cin.tie(0); ios::sync_with_stdio(false); cin >> H >> W; vector<string> maze(H); for (int i = 0; i < H; ++i) cin >> maze[i]; int sh, sw, gh, gw; cin >> sh >> sw >> gh >> gw; sh--, sw--, gh--, gw--; vector<vector<int>> dist[4]; for (int i = 0; i < 4; ++i) dist[i].assign(H, vector<int>(W, INF)); priority_queue<P, vector<P>, greater<P>> Q; Q.emplace(0, 0, sh, sw); dist[0][sh][sw] = 0; while (!Q.empty()) { int d, layer, h, w; tie(d, layer, h, w) = Q.top(); Q.pop(); for (int dir = 0; dir < 4; ++dir) { if (!cango(maze, layer, h, w, dir)) continue; int nh = h + DH[dir]; int nw = w + DW[dir]; if (dist[layer][nh][nw] > dist[layer][h][w] + 1) { dist[layer][nh][nw] = dist[layer][h][w] + 1; Q.emplace(dist[layer][nh][nw], layer, nh, nw); } } int nextlayer = (layer + 1) % LAYERS; if (dist[nextlayer][h][w] > dist[layer][h][w] + 1) { dist[nextlayer][h][w] = dist[layer][h][w] + 1; Q.emplace(dist[nextlayer][h][w], nextlayer, h, w); } } int ans = INF; for (int i = 0; i < 4; ++i) chmin(ans, dist[i][gh][gw]); if (ans == INF) { cout << -1 << endl; } else { cout << ans << endl; } }