少し実装が重ための問題です.
問題原案:@uni_kakurenbo
この問題は大きく以下の二つのパートの分割して解くことができます.
1. 全体像
MojaMoja 君の辿った経路を実際にシミュレーションすることで,洞窟内の構造を復元してみましょう.
具体的には,はじめ洞窟内はすべて通行不能なマスで埋まっているとして,MojaMoja 君が通った箇所だけを通行可能なマスの置き換えるということをします.
2. 情報の管理
一旦,盤面は の二次元配列などで管理することにします.
また,MojaMoja 君の行動を再現するために,MojaMoja 君の「位置」と「向き」を,変数で持っておきます.
位置については「グリッドの左上から 行目, 列目」のように 変数 を用いるとよいでしょう.
向きについては「はじめの向き」を として,右に 度回転する毎に というように 以上 未満の数値で扱うと便利です.
たとえば,はじめの向きを東とすると 東: ,南: ,西: ,北: のように対応します.ここでは変数 を用います.
3. 移動の表現
東を向いていたら を 増やす,南を向いていたら を 増やす,西を向いていたら を 減らす,北を向いていたら を 減らす...
というように移動を表現することもできますが,少々冗長です.
こういった移動方向の表現に適したテクニックがありますのでご紹介いたします.
「向き で正面へ マスだけ進んだときの, の変化」をそれぞれ とすると,
とあらわすことができます.(0-based indexing)
たとえば ですから,向き で正面(西)へ マスだけ進むことは のみを 減らすことに対応します.
4. 方向転換の表現
が 以上 未満だということを利用します.
剰余の性質より,右へ 度回転する動作を と表現したり,反対に左へ 度回転する動作を と表現したりすることができます.
基本的にはすべてのマスについて隣接する マスをすべて見るように全探索を行えばよいです.
通行不能なマスのみが対象となることに注意してください.
これをしっかりと実装しないとたとえば次のように左上のマスから移動がなかった場合に結果が変わってしまいます.
これは実装によっては左上のマスにも水晶が埋蔵されているとカウントされてしまうためです.
$$$$$ $.#@$ $#@@$ $@@@$ $$$$$
実際の実装時には奈落の代わりに周囲をさらに通行不能なマスで囲うことで判定が簡単になります.
詳細は「実装例」の項を参照してください.
言語によっては被除数の符号が負であるときに %
演算子の返り値も負になることに注意しましょう.
x%y
の代わりに (x%y+y)%y
を用いたりすることで回避が可能です.
F
ならば, を 増やし, を 増やし,洞窟の左上から 行目, 列目を通行可能なマスで置き換える.R
ならば, を で置き換える.L
ならば, を で置き換える.T
ならば, を で置き換える.全体で です.
(難易度順)
xxxxxxxxxx
using namespace std;
int main() {
int H, W, N; cin >> H >> W >> N;
string S; cin >> S;
vector grid(H+2, vector<int> (W+2, 1));
int di[4] = { 0, 1, 0, -1 }, dj[4] = { 1, 0, -1, 0 };
{
int i=1, j=1, d=0;
for(char s : S) {
grid[i][j] = false;
if(s == 'F') i += di[d], j += dj[d];
if(s == 'L') --d;
if(s == 'R') ++d;
if(s == 'T') ++++d;
d = (d+4)%4;
}
grid[i][j] = false;
}
int ans = 0;
for(int i=1; i<=H; ++i) for(int j=1; j<=W; ++j) {
if(!grid[i][j]) continue;
short cnt = 0;
for(int d=0; d<4; ++d) if(grid[i+di[d]][j+dj[d]]) ++cnt;
ans += cnt == 4;
}
cout << ans << "\n";
return 0;
}
xxxxxxxxxx
from itertools import product
H, W, N = map(int, input().split())
S = input()
H += 2; W += 2
grid = [[1] * W for _ in [0] * H]
dis, djs = (0, 1, 0, -1), (1, 0, -1, 0)
i, j, d = 1, 1, 0;
for s in S:
grid[i][j] = 0
if s == 'F': i += dis[d]; j += djs[d]
if s == 'L': d = (d-1)%4
if s == 'R': d = (d+1)%4
if s == 'T': d = (d+2)%4
grid[i][j] = 0
ans = 0
for i, j in product(range(1, H-1),range(1, W-1)):
if not grid[i][j]: continue
ans += all(grid[i+di][j+dj] for di, dj in zip(dis,djs))
print(ans)