B - 宮殿の衛兵 / Palace Guards Editorial by admin
gpt-6-astra-medium概要
各マスについて、自分自身と左右の隣のマスに衛兵がいるかを調べます。どこにも衛兵がいなければ、そのマスは守られていないので答えに数えます。
考察
衛兵が守る範囲は、自分の立っているマスと、その左右の隣のマスだけです。
逆に、マス \(i\) が守られているかを知りたい場合は、次の最大 \(3\) マスだけを確認すれば十分です。
- 左隣のマス \(i-1\)
- マス \(i\) 自身
- 右隣のマス \(i+1\)
この中に G があればマス \(i\) は守られており、なければ守られていません。ただし、廊下の外に当たるマスは確認しません。
例えば、S = "G...G" の場合、左端の衛兵は左から \(1,2\) 番目のマスを、右端の衛兵は \(4,5\) 番目のマスを守ります。したがって、守られていないのは中央の \(1\) マスです。
各マスについてすべての衛兵を調べる素朴な方法でも、時間計算量は \(O(N^2)\) なので今回の制約では十分間に合います。ただし、確認する場所を上記の最大 \(3\) マスに絞れば、より効率よく処理できます。
なお、. の個数を数えるだけでは、衛兵の隣にある守られたマスまで数えてしまうため、正しい答えになりません。
アルゴリズム
文字列の添字を \(0\) から \(N-1\) として扱います。
- 答えを格納する変数
ansを \(0\) にする。 - 各マス \(i\) について、以下を行う。
- 守られているかを表す変数
guardedをFalseにする。 - \(j=i-1,i,i+1\) のそれぞれについて、\(0 \leq j < N\) かつ
S[j] == 'G'なら、guardedをTrueにする。 guardedがFalseのままなら、ansに \(1\) を加える。
- 守られているかを表す変数
ansを出力する。
マス \(i\) を守れる衛兵がいる場所は \(i-1,i,i+1\) に限られるため、この判定で守られていないマスを漏れなく数えられます。
計算量
- 時間計算量: \(O(N)\)
各マスについて最大 \(3\) か所を確認します。 - 空間計算量: \(O(N)\)
入力文字列の保存に必要です。入力を除く追加の作業領域は \(O(1)\) です。
実装のポイント
文字列にアクセスする前に、
0 <= j < Nで添字が範囲内かを確認します。特に Python ではS[-1]が末尾の文字を指すため、この確認を省くと左端の判定を誤る可能性があります。衛兵は自分自身のマスも守るので、左右だけでなく
S[i]も確認します。guardedは、マスを調べるたびにFalseに初期化します。ソースコード
def main():
import sys
input = sys.stdin.readline
N = int(input())
S = input().strip()
ans = 0
for i in range(N):
guarded = False
for j in (i - 1, i, i + 1):
if 0 <= j < N and S[j] == 'G':
guarded = True
if not guarded:
ans += 1
print(ans)
main()
この解説は gpt-6-astra-medium によって生成されました。