题目地址:
https://www.acwing.com/problem/content/description/154/
有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。这片土地被分成
N
×
M
N×M
N×M个格子,每个格子里写着R
或者F
,R
代表这块土地被赐予了rainbow,F
代表这块土地被赐予了freda。现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着F
并且面积最大。但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为
S
S
S,它们将给你
3
×
S
3×S
3×S两银子。
输入格式:
第一行包括两个整数
N
,
M
N,M
N,M,表示矩形土地有
N
N
N行
M
M
M列。
接下来
N
N
N行,每行
M
M
M个用空格隔开的字符F
或R
,描述了矩形土地。每行末尾没有多余空格。
输出格式:
输出一个整数,表示你能得到多少银子,即(
3
×
3×
3×最大F矩形土地面积)的值。
数据范围:
1
≤
N
,
M
≤
1000
1≤N,M≤1000
1≤N,M≤1000
思路是单调栈。设矩阵为
A
A
A,我们考虑第
k
k
k行,先构造数组
a
a
a,
a
[
i
]
a[i]
a[i]表示从
A
[
k
]
[
i
]
A[k][i]
A[k][i]开始向上有多少个连续的F
,那么对于每个
k
k
k,可以求以
A
[
k
]
A[k]
A[k]为底的最大矩形面积,这就是求直方图中最大矩形面积的问题,可以用单调栈。参考https://blog.csdn.net/qq_46105170/article/details/115291803。代码如下:
#include <iostream>
#include <stack>
using namespace std;
const int N = 1010;
int m, n;
int a[N][N];
int res;
int calc(int a[]) {
int res = 0;
stack<int> stk;
for (int i = 1; i <= n; i++) {
while (stk.size() && a[stk.top()] > a[i]) {
int t = a[stk.top()]; stk.pop();
int l = stk.size() ? stk.top() : 0, r = i;
res = max(res, t * (r - l - 1));
}
stk.push(i);
}
while (stk.size()) {
int t = a[stk.top()]; stk.pop();
int l = stk.size() ? stk.top() : 0, r = n + 1;
res = max(res, t * (r - l - 1));
}
return res;
}
int main() {
cin >> m >> n;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) {
char ch;
cin >> ch;
if (ch == 'F') a[i][j] = 1;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
if (a[i][j]) a[i][j] += a[i - 1][j];
res = max(res, calc(a[i]));
}
printf("%d\n", res);
}
时间复杂度 O ( M N ) O(MN) O(MN),空间 O ( M ) O(M) O(M)。