解けなかったのでEditorial [1] を参考にした.
現在どの命令まで実行したのかと,二次元平面上の点でどの方向を向いているのかを状態として,原点から移動可能かどうかを動的計画法で実行すると 時間かかる.
まず,現在までの命令までに 'T' を何回実行したかで 軸方向に進むのか, 軸方向に進むのかが分かるので,どの方向を向いているのかの状態は必要ない.また,命令 'F' を実行するときは, 軸方向か 軸方向かのどちらか一方にしか進まないので,独立に到達可能かを計算できる.よって,状態数はどの命令までを実行したのかと,1次元上での座標で となり,各状態での遷移は2方向なので である.したがって,全体で 時間で計算できる.
実装は,先頭から命令を順番に実行した.このとき,命令 'F' を読むごとに遷移をして WA となりハマったので,連続する 'F' を数えて一気に移動するという実装を行った.
計算時間:
#include <bits/stdc++.h>
using namespace std;
int main() {
cin.tie(0); ios::sync_with_stdio(false);
string s;
int tx, ty;
cin >> s >> tx >> ty;
if (s.back() == 'F') s += "T";
const int n = s.size();
vector<vector<char>> dpx(2, vector<char>(2 * n + 2, false));
vector<vector<char>> dpy(2, vector<char>(2 * n + 2, false));
int idx = 0, d = 0, dir = 0;
while (idx < n && s[idx] == 'F') { ++d; ++idx; }
dpx[idx % 2][n + d] = dpy[idx % 2][n] = true;
int src = idx % 2, dst = (src + 1) % 2;
while (idx < n) {
fill(dpx[dst].begin(), dpx[dst].end(), false);
fill(dpy[dst].begin(), dpy[dst].end(), false);
if (s[idx] == 'T') {
for (int p = 0; p <= 2 * n; ++p) {
dpx[dst][p] |= dpx[src][p];
dpy[dst][p] |= dpy[src][p];
}
dir = (dir + 1) % 2;
}
else {
for (d = 0; idx < n && s[idx] == 'F'; ++idx) ++d;
--idx;
for (int p = 0; p <= 2 * n; ++p) {
if (dir == 0) {
if (0 <= p - d) dpx[dst][p - d] |= dpx[src][p];
if (p + d <= 2 * n) dpx[dst][p + d] |= dpx[src][p];
dpy[dst][p] |= dpy[src][p];
}
else {
if (0 <= p - d) dpy[dst][p - d] |= dpy[src][p];
if (p + d <= 2 * n) dpy[dst][p + d] |= dpy[src][p];
dpx[dst][p] |= dpx[src][p];
}
}
}
++idx;
swap(src, dst);
}
tx += n; ty += n;
if (dpx[src][tx] && dpy[src][ty]) cout << "Yes\n";
else cout << "No\n";
return 0;
}