【Python】BFSで動物が停止したときの最終的な向きを求めるプログラム
問題の概要
文字列 s は、いくつかの動物の初期状態を表しています。各動物は次の3種類のいずれかの値を取ります。
L: 動物が左へ移動することを表します
R: 動物が右へ移動することを表します
@: 動物がその場に静止していることを表します
ある方向へ移動中の動物は、進行方向にある他の動物を押し流しながら移動していきます。ただし、反対方向から同じタイミングで力を受けると、その場で静止します。すべての動物が停止したときの、それぞれの最終的な向きを求めるのがこの問題の目的です。
たとえば、入力が s = "@@L@R@@@@L" の場合、出力は "LLL@RRRLLL" となります。
解き方のアプローチ(BFS)
この問題は幅優先探索(BFS)を使うと効率的に解けます。力は時間ステップごとに隣接するマスへと伝わっていくため、「同じレベル(同時刻)に反対方向の力が同じマスへ到達した場合、その動物は静止する」という性質を利用できます。
具体的な手順は以下の通りです。
levels := 文字列 s と同じ長さのリストを作成し、すべて -1 で初期化する
q := 両端キュー(deque)を用意する
idx を 0 から s の長さまで順に処理する:
s[idx] が "R" または "L" の場合、q の末尾に (idx, 0, s[idx]) を追加する
l := 文字列 s を文字のリストに変換したもの
q が空になるまで以下を繰り返す:
(idx, new_level, dir) := q の先頭から要素を取り出す
levels[idx] が -1 の場合(まだ力が届いていないマス):
levels[idx] := new_level とし、l[idx] := dir を設定する
dir が "R" かつ idx + 1 が範囲内なら、q に (idx + 1, new_level + 1, dir) を追加する
dir が "L" かつ idx - 1 が 0 以上なら、q に (idx - 1, new_level + 1, dir) を追加する
levels[idx] が new_level と等しい場合(同時に別方向の力が到達):
l[idx] が dir と異なるなら、l[idx] := "@" として静止状態にする
最後に、l の要素を連結した文字列を返す
実装例
以下にPythonでの実装例を示します。
from collections import deque
class Solution:
def solve(self, s):
levels = [-1 for i in s]
q = deque()
for idx in range(len(s)):
if s[idx] == "R" or s[idx] == "L":
q.append((idx, 0, s[idx]))
l = list(s)
while q:
idx, new_level, dir = q.popleft()
if levels[idx] == -1:
levels[idx] = new_level
l[idx] = dir
if dir == "R" and idx + 1 < len(l):
q.append((idx + 1, new_level + 1, dir))
elif dir == "L" and idx - 1 >= 0:
q.append((idx - 1, new_level + 1, dir))
elif levels[idx] == new_level:
if l[idx] != dir:
l[idx] = "@"
return "".join(l)
ob = Solution()
s = "@@L@R@@@@L"
print(ob.solve(s))入力
"@@L@R@@@@L"
出力
LLL@RRRLLL
動作の解説
入力 "@@L@R@@@@L" の場合、力は次のように伝わります。
インデックス2の「L」: 左方向へ伝わり、インデックス0〜2が「L」になる
インデックス4の「R」: 右方向へ伝わり、インデックス4〜7が「R」になる
インデックス9の「L」: 左方向へ伝わり、インデックス8〜9が「L」になる
インデックス3には、左の「L」と右の「R」が互いに離れる方向へ移動するため、どちらの力も届きません。そのため「@」のまま静止します。このようにBFSでは、力が届いた順序(レベル)を記録することで、衝突による静止状態を正確に判定できます。
-
Pythonでポリゴンを初期状態にリセットするプログラムの実装方法
ここでは、n 個の頂点、n 本の反転軸(対称軸)、n 個の回転点を持つ多角形を考えます。反転軸と回転点については、以下の性質が成り立ちます。n が奇数の場合、各反転軸は1つの頂点と、その反対側の辺の中点を通ります。n が偶数の場合、半分の軸は向かい合う頂点同士を通り、残りの半分は向かい合う辺同士の中点を通ります。隣り合う2つの軸がなす角度は 360/2n 度です。問題の概要この多角形に対して操作を行います。操作には n 種類の回転器があり、k-rotator は軸 k を基準にして多角形を時計回りに (360 × k)/n 度回転させます。入力として、複数の整数ペアを含むリスト input_l
-
Pythonで制約付きの建物の最大高さを求めるプログラム
問題の概要整数 n と制約リスト restrictions が与えられたとします。私たちは都市に n 棟の新しい建物を一列に建てようとしていますが、高さに関するいくつかの制限があります。建物には左から順に 1 から n までの番号が付けられており、各制約は restrictions[i] = (id_i, max_height_i) の形式で表され、「id_i 番の建物の高さは max_height_i 以下でなければならない」ことを意味します。建物の高さに関する都市の規則は以下のとおりです。各建物の高さは 0 以上でなければなりません。1 番の建物(最初の建物)の高さは必ず 0 です。隣接す