ログインしてください。
公式
A - 宝の地図 / Treasure Map 解説 by admin
GPT 5.2 High概要
グリッド上の #(宝)があるマスをすべて含む、軸に平行な最小の長方形を求め、その面積(マス数)を計算します。
考察
宝があるマス全体を含む「最小の長方形」を作るには、宝が存在する行・列の範囲(最小行〜最大行、最小列〜最大列)を知れば十分です。
- 例えば、宝があるマスの座標が散らばっていても、
- 一番上にある宝の行番号 = 長方形の上端
- 一番下にある宝の行番号 = 長方形の下端
- 一番左にある宝の列番号 = 長方形の左端
- 一番右にある宝の列番号 = 長方形の右端
となり、これより内側に縮めるとどれかの宝がはみ出してしまうため、これが最小です。
素朴に「全ての長方形を列挙して、全部の # を含むか判定する」ような方法は、長方形の数が \(O(N^2M^2)\) もあり、\(N, M \le 1000\) では到底間に合いません(TLEになります)。
そこで、グリッドを1回走査して # の行・列の最小値と最大値だけを更新することで、最小長方形を直接求めます。
アルゴリズム
min_r, max_r, min_c, max_cを用意する(宝が見つかった行・列の最小/最大)。- 初期値は
min_r=N, max_r=-1, min_c=M, max_c=-1のように「まだ見つかっていない」状態にする。
- 初期値は
- グリッドを上から順に全探索する。
- マス \((i, j)\) が
#なら以下を更新する:min_r = min(min_r, i)max_r = max(max_r, i)min_c = min(min_c, j)max_c = max(max_c, j)
- マス \((i, j)\) が
- 最小長方形の高さは \((max_r - min_r + 1)\)、幅は \((max_c - min_c + 1)\)。
- 面積は
$\( (max_r - min_r + 1)\times(max_c - min_c + 1) \)$ を出力する。
※問題文より # は少なくとも1つ存在するため、最終的に必ず範囲が確定します。
計算量
- 時間計算量: \(O(NM)\)(全マスを1回見るだけ)
- 空間計算量: \(O(1)\)(範囲を表す変数だけ。入力文字列は1行ずつ処理)
実装のポイント
座標は 0-index(Pythonの
for i in range(N)/enumerate)で扱うとそのまま書けます。面積計算では+1を忘れないことが重要です。input().strip()で改行を除いてから文字を走査します。#が必ず存在する前提なので、範囲が未更新のままになるケースを特別扱いする必要はありません。ソースコード
import sys
def main():
input = sys.stdin.readline
N, M = map(int, input().split())
min_r, max_r = N, -1
min_c, max_c = M, -1
for i in range(N):
s = input().strip()
for j, ch in enumerate(s):
if ch == '#':
if i < min_r: min_r = i
if i > max_r: max_r = i
if j < min_c: min_c = j
if j > max_c: max_c = j
area = (max_r - min_r + 1) * (max_c - min_c + 1)
print(area)
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
投稿日時:
最終更新: