题目背景
有一天,小猫 rainbow 和 freda 来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
题目描述
这片土地被分成 N×MN\times MN×M 个格子,每个格子里写着 R 或者 F,R 代表这块土地被赐予了 rainbow,F 代表这块土地被赐予了 freda。
现在 freda 要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着 F 并且面积最大。
但是 rainbow 和 freda 的 OI 水平都弱爆了,找不出这块土地,而蓝兔也想看 freda 卖萌(她显然是不会编程的......),所以它们决定,如果你找到的最大的土地面积为 SSS,它们每人给你 SSS 两银子。
输入格式
第一行两个整数 NNN,MMM,表示矩形土地有 NNN 行 MMM 列。
接下来 NNN 行,每行 MMM 个用空格隔开的字符 F 或 R,描述了矩形土地。
输出格式
输出一个整数,表示你能得到多少银子,即 3×S3\times S3×S 的值。
输入输出样例 #1
输入 #1
5 6
R F F F F F
F F F F F F
R R R F F F
F F F F F F
F F F F F F
输出 #1
45
说明/提示
对于 50%50\%50% 的数据,1≤N,M≤2001 \leq N, M \leq 2001≤N,M≤200。
对于 100%100\%100% 的数据,1≤N,M≤10001 \leq N, M \leq 10001≤N,M≤1000。
【题目解析】
1. 预处理高度数组
cpp
if(c=='F') h[i][j] = h[i-1][j] + 1;
h[i][j]表示以第i行为底、第j列向上连续 'F' 的个数。- 这样就把问题转化为求每一行作为底的直方图最大矩形面积。
2. 单调栈求每行最大矩形面积
对每一行 i:
- 用单调递增栈(存列下标
j),栈内h[i][j]严格递增。 - 遇到
h[i][j]小于等于栈顶高度时,弹出栈顶并确定它的右边界。 - 左边界是栈内前一个元素的下标,右边界是当前列
j。 - 弹出后,矩形面积 =
高度 × (右边界 - 左边界 - 1)。
3. 关键变量含义
| 变量 | 含义 |
|---|---|
h[i][j] |
第 i 行第 j 列向上连续 'F' 的高度 |
s[t] |
单调栈,存的是列下标 |
l[j] |
第 j 列作为当前栈顶时的左边界 |
r[j] |
第 j 列作为弹出元素时的右边界 |
4. 对每一行的处理
cpp
// 从左向右扫描,找右边界
for(int j=1;j<=m;j++){
while(t>0 && h[i][s[t]] >= h[i][j]){
r[s[t--]] = j; // 栈顶的右边界是 j
}
l[j] = s[t]; // 当前 j 的左边界是栈顶
s[++t] = j;
}
// 扫完后,栈内剩余元素的右边界是 m+1
while(t>0) r[s[t--]] = m+1;
// 计算该行所有矩形面积
for(int j=1;j<=m;j++){
a = max(a, (r[j] - l[j] - 1) * h[i][j]);
}
5. 最终答案
cpp
cout << a * 3;
因为每个 'F' 格子代表 3 个单位面积(题目隐含),所以最后乘以 3。
样例验证
输入:
4 4
F F F F
F F F F
F F F F
F F F F
- 每行高度都是
[4,4,4,4] - 最大矩形:整行 4×4=16 个格子
- 输出:16×3=48
如果有一个 2×3 的 'F' 矩形,面积就是 6×3=18。
时间复杂度
- 每行扫描
O(m),共n行 - 总复杂度
O(n×m),完美通过n,m ≤ 1000的数据。
【贴上代码】
cpp
#include <iostream>
using namespace std;
const int N=1008;
int n,m,h[N][N],t,s[N],l[N],r[N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char c;
cin>>c;
if(c=='F') h[i][j]=h[i-1][j]+1;
}
}
int a=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
while(t>0&&h[i][s[t]]>=h[i][j])
{
r[s[t--]]=j;
}
l[j]=s[t];
s[++t]=j;
}
while(t>0)
{
r[s[t--]]=m+1;
}
for(int j=1;j<=m;j++)
{
a=max(a,(r[j]-l[j]-1)*h[i][j]);
}
}
cout<<a*3;
return 0;
}