> makibishi throw|

ABC082D - FT Robot

問題概要

リンク

二次元平面の原点にロボットがある。ロボットは最初 x 軸の正の向きを向いている。 ロボットは与えられた命令列ssにしたがって動く。ssは’F’と’T’のみからなり、それぞれ下記のような操作に対応する。

  • ‘F’: 今の向きに11移動する。
  • ‘T’: 時計回り、または反時計回りに 90 度向きを変える。

命令列ssを全て実行後、座標(xx,yy)にいることができるか判定せよ。

制約

  • ssは’F’と’T’のみからなる。
  • 1s80001 \leq |s| \leq 8000
  • x,ys|x|,|y| \leq |s|

解法

まずは、操作の選択の余地がある、‘T’の操作について考えてみる。

ロボットは’T’で時計回り、または反時計回りに 90 度向きを変える。つまりどちらに向きが変わっても、今まで x 軸方向を向いていた場合は y 軸方向に、y 軸方向を向いていた場合は x 軸方向に向きが変わるということになる。

ということは、文字列ss中のある’T’において、次の’T’が出現するまでの’F’の進行方向は、過去にどのようなターンを選択していたとしても x 軸方向、y 軸方向のどちらかに固定される。

例として、FFTTFFFTFTFFFFというssが与えられた場合を考える。この時、最初のFFはもちろん+x 方向になるが、 次のTTでどのようなターンの仕方をしたとしても、+x 方向から 0 度、もしくは 180 度のターンとなるため、次のFFFは+x 方向、もしくは-x 方向になる。次のTでは-90 度もしくは 90 度のターンとなるため、Fは-y 方向もしくは+y 方向となる。このようにして、Fの固まりについて、以下のようにありうる進行方向を絞ることができる。

FF TT FFF T F T FFFFについて

  • FF: +x
  • FFF: +x or -x
  • F: +y or -y
  • FFFF: +x or -x

初めのFFを初期位置が(22,00)であると読み替えることで無視すると、全ての F のグループを x 軸 に影響するものと y 軸に影響するものに分類できる。この分類操作により、この問題を以下のような問題に置き換えることができる。

変換された問題

ロボットは最初原点(aa,0)にいる。

集合 X={x1,x2,...,xa}X = \{x_1,x_2,...,x_a\}と集合 Y={y1,y2,...,yb}Y = \{y_1,y_2,...,y_b\}が与えられる。ロボットは集合 XX から要素xix_iを取り出して+x 方向または-x 方向に移動するか、YYから要素yiy_iを取り出して+y 方向または-y 方向に移動する。

X,YX,Yが空になるまで移動を行った後、座標(x,y)(x,y)にいることができるか判定せよ。

変換された問題を解く

変換された問題は、XXを使ってxxにぴったり到着できることと、YYを使ってyyにぴったり到着できることをそれぞれ独立に考えることができる。しかも、これらは同じ解法で解ける。

XXを使ってxxにぴったり到着できるかは、DP により解くことができる。具体的には以下のような DP テーブルを考えればよい。

DP[i][j]={\rm DP}[i][j] = XXの要素を最初の i 個使って座標 j に到達できるか

遷移式

DP[i][j]=DP[i1][jxi]DP[i1][j+xi]{\rm DP}[i][j] = {\rm DP}[i-1][j - x_i] \lor {\rm DP}[i-1][j + x_i]

(\lor は 論理和 OR を表す)

制約条件から0i80000 \leq i \leq 80008000j8000-8000 \leq j \leq 8000におさまる。

まとめと感想

この問題を解くには、まずssを 1 文字ずつ見て変換問題のための集合X,YX,Yを作り(O(s)O(|s|))xxに到達できることとyyに到達できることを独立に DP によって解けばよい。(O(s2)O(|s|^2))

一見難しそうだがシンプルな複数の問題に分解して解くことができ、解いた後気持ちがよい問題だった。