[AtCoder] ABC 176 D – Wizard in Maze
問題
方針
領域の作成
徒歩で行くことができるマスをグループ化し、IDを振ります。マス \( (i, j) \) の ID が \( 0\) であることを \( G(i, j) = 0 \) と表し、そのマスから徒歩でいけるマスの ID は \( 0\) となります。 これらは幅優先探索で求めることができます。
隣接リストの作成
道であるマス \( (i, j) \) から \( |i + x| \leq 2 \wedge |i + y| \leq 2 \) を満たす \( x, y\) について、マス \( (i + x, j + y) \) が道であるときワープ魔法で移動することができます。このとき、\( G(i, j) \neq G(i + x, j + y) \) であれば辺として追加します。
隣接リストの探索
隣接リストが作成できたら、\( G(C_w, C_h) \) から探索し、\( G(D_w, D_h) \) までの最短距離を調べます。
コード
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { int H, W, C_h, C_w, D_h, D_w; cin >> H >> W >> C_h >> C_w >> D_h >> D_w; C_h--; C_w--; D_h--; D_w--; char S[H][W]; for (int i = 0; i < H; i++) { string s; cin >> s; for (int j = 0; j < W; j++) { S[i][j] = s[j]; } } int MAX = 100000000; int G[H][W]; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { G[i][j] = -1; } } int dx[] = {1, -1, 0, 0}; int dy[] = {0, 0, -1, 1}; deque<pair<int, int>> q; int idx = 0; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { if (G[i][j] == -1 && S[i][j] == '.') { G[i][j] = idx; vector<pair<int, int>> v; q.push_back(make_pair(i, j)); while (!q.empty()) { pair<int, int> p = q.front(); q.pop_front(); int x = p.second; int y = p.first; for (int k = 0; k < 4; k++) { int nx = x + dx[k]; int ny = y + dy[k]; if (nx < 0 || ny < 0 || nx >= W || ny >= H) continue; if (S[ny][nx] == '.' && G[ny][nx] == -1) { G[ny][nx] = idx; q.push_back(make_pair(ny, nx)); } } } idx++; } } } int ex[] = {1, 1, -1, -1, 2, 2, 2, 2, 2, 1, 1, 0, 0, -1, -1, -2, -2, -2, -2, -2}; int ey[] = {1, -1, 1, -1, -2, -1, 0, 1, 2, 2, -2, 2, -2, 2, -2, 2, 1, 0, 1, 2}; set<int> adj[idx]; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { if (G[i][j] == -1) continue; for (int k = 0; k < 20; k++) { int nx = j + ex[k]; int ny = i + ey[k]; if (nx < 0 || ny < 0 || nx >= W || ny >= H) continue; if (S[ny][nx] == '.' && G[i][j] != G[ny][nx]) { adj[G[i][j]].insert(G[ny][nx]); adj[G[ny][nx]].insert(G[i][j]); } } } } int L[idx]; for (int i = 0; i < idx; i++) { L[i] = MAX; } L[G[C_h][C_w]] = 0; deque<int> dq; dq.push_back(G[C_h][C_w]); while (!dq.empty()) { int p = dq.front(); dq.pop_front(); for (int i : adj[p]) { if (L[p] + 1 < L[i]) { L[i] = L[p] + 1; dq.push_back(i); } } } if (L[G[D_h][D_w]] != MAX) { cout << L[G[D_h][D_w]] << "\n"; } else { cout << "-1\n"; } return 0; }
ディスカッション
コメント一覧
まだ、コメントがありません