AOJ DPL_3_B Largest Rectangle
備忘録
問題
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_3_B&lang=jp
回答
import sys, os, math, bisect, itertools, collections, heapq, queue, copy, array # from scipy.sparse.csgraph import csgraph_from_dense, floyd_warshall # from decimal import Decimal # from collections import defaultdict, deque sys.setrecursionlimit(10000000) ii = lambda: int(sys.stdin.buffer.readline().rstrip()) il = lambda: list(map(int, sys.stdin.buffer.readline().split())) fl = lambda: list(map(float, sys.stdin.buffer.readline().split())) iln = lambda n: [int(sys.stdin.buffer.readline().rstrip()) for _ in range(n)] iss = lambda: sys.stdin.buffer.readline().decode().rstrip() sl = lambda: list(map(str, sys.stdin.buffer.readline().decode().split())) isn = lambda n: [sys.stdin.buffer.readline().decode().rstrip() for _ in range(n)] lcm = lambda x, y: (x * y) // math.gcd(x, y) MOD = 10 ** 9 + 7 INF = float('inf') def main(): if os.getenv("LOCAL"): sys.stdin = open("input.txt", "r") H, W = il() T = [il() for _ in range(H)] dp = [[0] * W for _ in range(H)] ret = 0 # ヒストグラムの作成 for h in range(H): for w in range(W): if T[h][w] == 0: dp[h][w] = max(1, dp[h - 1][w] + 1) stack = [] # 長方形の最大面積計算 for w in range(W): position = -1 while len(stack) > 0 and stack[-1][0] > dp[h][w]: height, position = stack.pop() ret = max(ret, height * (w-position)) if len(stack) == 0 or (len(stack) > 0 and stack[-1][0] < dp[h][w]): position = w if position == -1 else position stack.append((dp[h][w], position)) for height, position in stack: ret = max(ret, height * (W - position)) print(ret) if __name__ == '__main__': main()
考え方
螺旋本より、動的計画法の問題。
初めに、各h(0 <= h <= H
)を1行ずつ、動的計画法で縦の高さを求める。
この高さと、高さが存在する列から長方形の面積を求める。
まず、高さについて。
1行ずつタイルを確認し、汚れていない場合にはmax(1,1行上のタイル + 1)
として、
汚れていないタイルの縦に積みあがった最大値を求める。
次に、横幅について。
高さと、その高さがどの列に存在するかをスタックに積んでおく。
スタックからデータを順に取り出すと、高さと高さが存在する列の情報から面積を求めることができる。
さらにスタックからデータを順に取り出していくと、高さが高い列から低い列へ向かって、データを取り出すことが出来る。
つまり、先に取り出されるデータの方が高さを持っているため、あとから取り出されるデータは、
一番初めに取り出されたデータの列までは横幅を持つことが出来る。
例えば、(高さ, 列) とした時、
スタック = [(1, 0), (2, 1), (4, 2), (7, 3)]のデータを一つずつ取り出すと
1つ目のデータ(7, 3)は高さ7, 横幅1で面積7
2つ目のデータは、自身の存在する列と、自分より高い(7, 3)の列を使用することが出来るため
高さ4, 横幅2で面積8
3つ目のデータは、自身の存在する列と、自分より高い(7, 3),(4, 2)の列を使用することができるため
高さ2, 横幅3で面積6 ... と、各列の取りうる最大面積を求めることができる。