一个地图上有若干障碍,问允许出现一个障碍的最大子矩形为多大?
最大子矩形改编
#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 #.#.. ....# ..#.. ....# */