AOJ 2861 RPG Maker
解法
典型構築だと思われる。
4n - 1, 4m - 1 であることが重要で、この制約のためにすべてのマスを回収するようなパスが存在する。
イメージとしては蛇のようにうねうねしながら移動するというもの。
あとは実装を楽にするだけ。とりあえず始点を無視して (0, 0) から始める。
とりあえず (0, 0) -> (h-1, 0) へ一直線に移動する。
その後は蛇のように上に上がっていくと、いずれ (0, 0) にたどり着く。
こうしてできたパスはループになる。
あとは、'@' の位置が始点になるようにパスをずらし (rotate する)、末尾にある余計な移動を削除すればよい。
ソースコード
#include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; int main() { int h, w; cin >> h >> w; vector<string> s(h); int sy = -1, sx = -1; for(int i = 0; i < h; ++i) { cin >> s[i]; for(int j = 0; j < w; ++j) { if(s[i][j] == '@') { sy = i, sx = j; } } } vector<pii> path; for(int i = 0; i < h; ++i) { path.emplace_back(i, 0); } function<void(int, int, int)> snake = [&] (int y, int x, int dx) { path.emplace_back(y, x); if(x + 2 * dx == 0 && y == 0) { path.emplace_back(0, 1); return; } if(x + dx < 2 || w <= x + dx) { path.emplace_back(y - 1, x); dx *= -1; y -= 2; snake(y, x, dx); } else { snake(y, x + dx, dx); } }; snake(h - 1, 1, 1); rotate(begin(path), find(begin(path), end(path), make_pair(sy, sx)), end(path)); while(s[path.back().first][path.back().second] != '*') { path.pop_back(); } for(auto const& p : path) { const int y = p.first, x = p.second; if(s[y][x] == '.') { s[y][x] = '#'; } } for(auto const& t : s) { cout << t << endl; } }
感想
焦ると実装が沼になりそう。落ち着いて処理したい。