AtCoder Beginner Contest 182 E – Akari をPython3で解く

Share

AtCoder上にある問題のうち、AtCoder Problemsでdiff 800以上と判定されているものを順番に解いていく企画。
基本的な考え方は全てコード中のコメントに入れてあるので、参照のこと。

出典:
AtCoder Beginner Contest 182 E – Akari

ライト毎に全てを確認しているとTLEなので、可能な限り簡単な数え方を考える必要がある。

# AtCoder Beginner Contest 182 E - Akari
# https://atcoder.jp/contests/abc182/tasks/abc182_e
# tag: グリッド スキャン 数え上げ

# 上下左右の方向をそれぞれ独立したものとして考えると、楽。
# ライトが現れた後を明るく、ブロックが現れた後を暗くするだけでいい。

# 具体的な例として、仮に ライト: o , ブロック: # とすると、
# ...o...#..
# のような並びがあり、明かりが届く範囲を 1 にしたいとする。
# 左→右 の方向だけに注目すると、
# 0001111000
# 右→左 だと
# 1111000000
# これを合成すると、
# 1111111000
# という具合にできる。縦方向も同様。

def main():
H, W, N, M = map(int, input().split())
lights = [list(map(int, input().split())) for _ in range(N)]
blocks = [list(map(int, input().split())) for _ in range(M)]

# 0: 空白, 1: ライト, -1: ブロック
field = [[0] * W for _ in range(H)]
for ly, lx in lights:
field[ly-1][lx-1] = 1
for by, bx in blocks:
field[by-1][bx-1] = -1

result = [[0] * W for _ in range(H)]

for y in range(H):
# 左 → 右
lit = 0
for x in range(W):
if field[y][x] == -1:
lit = 0
continue
if field[y][x] == 1:
lit = 1
if lit == 1:
result[y][x] = 1
# 右 → 左
lit = 0
for x in range(W-1, -1, -1):
if field[y][x] == -1:
lit = 0
continue
if field[y][x] == 1:
lit = 1
if lit == 1:
result[y][x] = 1

for x in range(W):
# 上 → 下
lit = 0
for y in range(H):
if field[y][x] == -1:
lit = 0
continue
if field[y][x] == 1:
lit = 1
if lit == 1:
result[y][x] = 1
# 下 → 上
lit = 0
for y in range(H-1, -1, -1):
if field[y][x] == -1:
lit = 0
continue
if field[y][x] == 1:
lit = 1
if lit == 1:
result[y][x] = 1

# 数えて回答
print(sum(result[y][x]==1 for y in range(H) for x in range(W)))

main()
Share

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です