けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 385 B - Santa Claus 1 (5Q, 灰色, 200 点)

二次元グリッド上のシミュレーション問題!

問題概要

 H \times W のグリッドが与えられる。各マスは

  • '.':通路マス
  • '#':壁マス
  • '@':アイテムマス

のいずれかである。最初、マス  (x, y) にいる。

今、グリッド上で文字列  T に示す移動をする(U, D, L, R のいずれか)。ただし、移動先が壁マスである場合は移動しない。移動先のマスがアイテムマスであれば、アイテムを回収する。一度アイテムを回収すると、空きマスとなる。

すべての移動を終えたあとのマスの位置と、回収したアイテムの個数を求めよ。

制約

  •  3 \le H, W \le 100
  •  1 \le |T| \le 10^{4}

考えたこと

文字列  T の各文字  c に対して、マス  (x, y) から次の移動をする。

  •  c = 'U' のとき: x が 1 小さくなる
  •  c = 'D' のとき: x が 1 大きくなる
  •  c = 'L' のとき: y が 1 小さくなる
  •  c = 'R' のとき: y が 1 大きくなる

ただし、移動後のマスが壁である場合は、マスを現状維持とする。

さらに「一度回収したアイテムはなくなる」を実現するには、次のようにすればよい。


グリッドの該当のマスを '@' から '.' に更新する


コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int H, W, x, y;
    cin >> H >> W >> x >> y, x--, y--;
    vector<string> S(H);
    for (int i = 0; i < H; i++) cin >> S[i];
    string T;
    cin >> T;

    int res = 0;
    for (auto c : T) {
        int x2 = x, y2 = y;
        if (c == 'U') x2--;
        else if (c == 'D') x2++;
        else if (c == 'L') y2--;
        else y2++;

        if (S[x2][y2] == '#') continue;
        else {
            if (S[x2][y2] == '@') {
                res++;
                S[x2][y2] = '.';  // 一度回収したら空きマスにする
            }
            x = x2, y = y2;
        }
    }
    cout << x+1 << " " << y+1 << " " << res << endl;
}