求只包含 F
的最大子矩形面积。
悬线法。
记 $up_{i,j}$ 表示 $(i,j)$ 向上延伸最远能到第几行,$l_{i,j}, r_{i,j}$ 为一条悬线向左向右延伸到哪里。
如果 $a_{i-1,j}$ 是障碍物,那就不要通过上一行转移;否则 $l,r$ 分别取 $\max,\min$。
细节还挺多的,要考虑开闭区间问题,调了十分钟左右,太菜了。
PS: 如果处理的矩阵是一个前缀,在转移的时候可以直接记录。
#include <bits/stdc++.h>
using namespace std;
const int N = 1015;
int n, m;
bool st[N][N];
int up[N][N], l[N][N], r[N][N], ans = 0;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
char c; scanf(" %c", &c);
st[i][j] = c == 'R';
}
for (int i = 1; i <= n; i++) l[i][0] = 1, r[i][m + 1] = m;
for (int i = 1; i <= m; i++) up[0][i] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (st[i][j]) up[i][j] = i + 1;
else up[i][j] = up[i - 1][j];
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (st[i][j]) l[i][j] = j + 1;
else l[i][j] = l[i][j - 1];
}
for (int i = 1; i <= n; i++)
for (int j = m; j >= 1; j--) {
if (st[i][j]) r[i][j] = j - 1;
else r[i][j] = r[i][j + 1];
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (i > 1 && !st[i - 1][j]) {
l[i][j] = max(l[i][j], l[i - 1][j]);
r[i][j] = min(r[i][j], r[i - 1][j]);
}
if (!st[i][j]) ans = max(ans, (i - up[i][j] + 1) * (r[i][j] - l[i][j] + 1));
}
// for (int i = 1; i <= n; i++, puts(""))
// for (int j = 1; j <= m; j++) cout << up[i][j] << ' ';
printf("%d\n", ans * 3);
return 0;
}