题意
题解
悬线法 DP
悬线法 D P DP DP 的基本思想,即求解每一个点向上可拓展的高度以及以这个高度为高的矩形的最长宽,以更新答案。此时可保证遍历所有可能的面积最大的矩形。
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1005;
char mat[maxn][maxn];
int K, N, M, L[maxn][maxn], R[maxn][maxn], U[maxn][maxn];
int main()
{
scanf("%d", &K);
while (K--)
{
scanf("%d%d", &N, &M);
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
scanf(" %c", mat[i] + j);
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
L[i][j] = R[i][j] = U[i][j] = 0;
for (int i = 0; i < N; ++i)
for (int j = 1; j < M; ++j)
if (mat[i][j] == 'F' && mat[i][j - 1] == 'F')
L[i][j] = L[i][j - 1] + 1;
for (int i = 0; i < N; ++i)
for (int j = M - 2; j >= 0; --j)
if (mat[i][j] == 'F' && mat[i][j + 1] == 'F')
R[i][j] = R[i][j + 1] + 1;
int res = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
if (mat[i][j] == 'F')
{
if (i && mat[i - 1][j] == 'F')
{
U[i][j] = U[i - 1][j] + 1;
L[i][j] = min(L[i][j], L[i - 1][j]);
R[i][j] = min(R[i][j], R[i - 1][j]);
}
res = max(res, (U[i][j] + 1) * (L[i][j] + R[i][j] + 1));
}
printf("%d\n", 3 * res);
}
return 0;
}
单调栈
枚举每一行向上可拓展的最大高度,问题转化为求解单位宽度、高度不等的连续排列矩形所能构成的矩形的最大面积。
可以观察到,当矩形高度递增时,每一个高度都是最大面积矩形的备选答案;若出现高度小于上一个的矩形,那么对于之后的矩形,所组成的矩形高度受限于这个高度较小的矩形。于是用单调栈维护一个高度递增的矩形,当出现高度较小的矩形时,将其不断与之前的高度比它大的矩形在宽度上进行合并,同时更新答案。
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1005;
char mat[maxn][maxn];
int K, N, M, top, h[maxn], st[maxn], w[maxn];
int solve(int i)
{
int res = 0;
top = 0;
h[M] = st[++top] = -1;
for (int i = 0; i <= M; ++i)
{
if (h[i] > st[top])
st[++top] = h[i], w[top] = 1;
else
{
int l = 0;
while (st[top] > h[i])
l += w[top], res = max(res, st[top] * l), --top;
st[++top] = h[i], w[top] = l + 1;
}
}
return res;
}
int main()
{
scanf("%d", &K);
while (K--)
{
scanf("%d%d", &N, &M);
memset(h, 0, sizeof(int) * M);
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
scanf(" %c", mat[i] + j);
int res = 0;
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
h[j] = mat[i][j] == 'F' ? h[j] + 1 : 0;
res = max(res, solve(i));
}
printf("%d\n", 3 * res);
}
return 0;
}