結果
| 問題 |
No.2473 Fraises dans une boîte
|
| コンテスト | |
| ユーザー |
👑 SPD_9X2
|
| 提出日時 | 2023-08-07 04:14:30 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 2,402 ms / 4,000 ms |
| コード長 | 3,462 bytes |
| コンパイル時間 | 439 ms |
| コンパイル使用メモリ | 82,364 KB |
| 実行使用メモリ | 81,308 KB |
| 最終ジャッジ日時 | 2024-11-07 08:44:32 |
| 合計ジャッジ時間 | 42,226 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 65 |
ソースコード
"""
Fraises dans une boîte(6)
想定解
3乗計算量Ver
色々と整っていないので、あまりに読み辛いです
rinさんのを読んでください…
"""
import sys
from sys import stdin
H,W = map(int,stdin.readline().split())
S = [list(map(int,stdin.readline().split())) for i in range(H)]
# 制約チェック
#assert 1 <= H <= 22
#assert 1 <= W <= 22
assert len(S) == H
for s in S:
assert len(s) == W
for i in s:
assert i == 0 or i == 1
# 領域の和を高速に導出するための2次元累積和
SSum = [[0] * (W+1) for i in range(H+1)]
for i in range(H):
for j in range(W):
SSum[i+1][j+1] += S[i][j]
for i in range(H):
for j in range(W+1):
SSum[i+1][j] += SSum[i][j]
for i in range(H+1):
for j in range(W):
SSum[i][j+1] += SSum[i][j]
# 同じ行で、i番目からみて直左にあるjのインデックスを記録
SR = [[-1] * W for i in range(H)]
for i in range(H):
for j in range(W):
if S[i][j] == 1:
SR[i][j] = j
for i in range(H):
for j in range(W-1):
SR[i][j+1] = max(SR[i][j+1] , SR[i][j])
# メモ化用の2次元list
inf = float("inf")
lis = [[inf] * (W+1) for i in range(H+1)]
for j in range(W+1):
lis[H][j] = 0
for i in range(H+1):
lis[i][W] = 0
# ここからdp
for x1 in range(H-1,-1,-1): #左上のx座標
for y1 in range(W-1,-1,-1): #左上のy座標
if SSum[H][W] - SSum[x1][W] - SSum[H][y1] + SSum[x1][y1] <= 1:
lis[x1][y1] = 0
continue
# ここから、最小値の導出処理
now_ans = inf
# 左上領域の空行カウント用の配列
zerox = [0]
zeroy = [0]
for tmpx in range(x1,H):
nsum = SSum[tmpx+1][W] - SSum[tmpx][W] - SSum[tmpx+1][y1] + SSum[tmpx][y1]
zerox.append(zerox[-1] + (min(1,nsum)^1) )
for tmpy in range(y1,W):
nsum = SSum[H][tmpy+1] - SSum[H][tmpy] - SSum[x1][tmpy+1] + SSum[x1][tmpy]
zeroy.append(zeroy[-1] + (min(1,nsum)^1) )
for xmid in range(H,x1-1,-1):
# ymidは一意に決まる
if xmid == H:
ymids = [i for i in range(y1,W+1)]
elif xmid == H-1:
ymids = [max(y1,SR[xmid][-1]+1)]
else:
ymids = [max(ymids[0] , SR[xmid][-1]+1)]
for ymid in ymids:
assert x1 <= xmid <= H
assert y1 <= ymid <= W
#右下が0で無い場合、駄目
if SSum[H][W] - SSum[xmid][W] - SSum[H][ymid] + SSum[xmid][ymid] != 0:
continue
#左上・右下共に0の場合は推移の意味が無いのでダメ
if (xmid-x1) * (ymid-y1) == 0 and (H-xmid) * (W-ymid) == 0:
continue
cost = 0
# 左上区間の1の個数
lu1 = SSum[xmid][ymid] - SSum[xmid][y1] - SSum[x1][ymid] + SSum[x1][y1]
cost += (xmid-x1-zerox[xmid-x1]) * (ymid-y1-zeroy[ymid-y1]) - lu1
# 左下と右上
cost += lis[xmid][y1] + lis[x1][ymid]
# デバッグ用
#print (x1,y1,xmid,ymid,"cost",cost,lu1)
if xmid == x1 and ymid == y1:
continue
now_ans = min(now_ans , cost)
lis[x1][y1] = now_ans
print (lis[0][0])
SPD_9X2