Petrozavodsk Winter Camp, Warsaw U, 2014, A The Carpet
一个地图上有若干障碍,问允许出现一个障碍的最大子矩形为多大?
最大子矩形改编
#include<bits/stdc++.h> using namespace std; #define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i) #define dwn(i, j, k) for (int i = int(j); i >= int(k); -- i) const int N = 2007; int n, m, l[N][2], r[N][2], h[N][2]; char s[N][N]; int main() { scanf("%d%d", &n, &m); rep(i, 1, n) scanf("%s", s[i] + 1); int ans = 0; // 枚举障碍不在悬线上 // l[j][0]表示最左扩展(不能包含障碍),l[j][1]表示最右扩展(能包含障碍) rep(j, 1, m) l[j][0] = l[j][1] = j, r[j][0] = r[j][1] = m + 1 - j; rep(i, 1, n) { int lb0 = 0, lb1 = 0; rep(j, 1, m) { if (s[i][j] == '.') { h[j][0] ++; ans = max(ans, h[j][0]); l[j][1] = max(min(l[j][1], j - lb0), min(l[j][0], j - lb1)); l[j][0] = min(l[j][0], j - lb0); } else { lb1 = lb0; lb0 = j; l[j][0] = l[j][1] = j; h[j][0] = 0; } } int rb0 = m + 1, rb1 = m + 1; dwn(j, m, 1) { if (s[i][j] == '.') { r[j][1] = max(min(r[j][1], rb0 - j), min(r[j][0], rb1 - j)); r[j][0] = min(r[j][0], rb0 - j); ans = max(ans, (l[j][0] + r[j][0] - 1) * h[j][0]); ans = max(ans, (l[j][0] + r[j][1] - 1) * h[j][0]); ans = max(ans, (l[j][1] + r[j][0] - 1) * h[j][0]); } else { rb1 = rb0; rb0 = j; r[j][0] = r[j][1] = m + 1 - j; } } } // 枚举障碍在悬线上 // 这时候的l[j][0]表示没有障碍的悬线最左扩展,l[j][1]表示有障碍的悬线最左扩展 rep(j, 1, m) l[j][0] = l[j][1] = j, r[j][0] = r[j][1] = m + 1 - j, h[j][0] = h[j][1] = 0; rep(i, 1, n) { int lb = 0; rep(j, 1, m) { if (s[i][j] == '.') { h[j][0] ++; h[j][1] ++; l[j][0] = min(l[j][0], j - lb); l[j][1] = min(l[j][1], j - lb); } else { l[j][1] = min(l[j][0], j - lb); h[j][1] = h[j][0] + 1; h[j][0] = 0; l[j][0] = j; lb = j; } } int rb = m + 1; dwn(j, m, 1) { if (s[i][j] == '.') { r[j][0] = min(r[j][0], rb - j); r[j][1] = min(r[j][1], rb - j); } else { r[j][1] = min(r[j][0], rb - j); r[j][0] = m + 1 - j; rb = j; } } rep(j, 1, m) { ans = max(ans, h[j][1] * (l[j][1] + r[j][1] - 1)); } } cout << ans << '\n'; } /* 4 5 #.#.. ....# ..#.. ....# */