P4147 玉蟾宫

题目背景

有一天,小猫 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 个用空格隔开的字符 FR,描述了矩形土地。

输出格式

输出一个整数,表示你能得到多少银子,即 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;
}
相关推荐
计算机安禾11 分钟前
【数据库系统原理】第4篇:关系数据结构的形式化定义:域、笛卡尔积与关系模式
数据结构·数据库·算法
手写码匠24 分钟前
手写 DeepSeek 推理引擎优化:从 FP16 到 INT4 的量化加速实战
人工智能·深度学习·算法·aigc
GuWenyue25 分钟前
LeetCode 76 最小覆盖子串|JS 滑动窗口标准解法
前端·算法·面试
一只齐刘海的猫1 小时前
【Leetcode】移动零
算法·leetcode·职场和发展
指针战神1 小时前
synchronized简易版Redis版跳表实现(注释干货)
数据结构
王老师青少年编程1 小时前
信奥赛C++提高组csp-s之搜索进阶(迭代加深IDDFS)
c++·csp·信奥赛·csp-s·提高组·iddfs·埃及分数
liulilittle2 小时前
我从 BBRv1 到 KCC 的思考
网络·c++·tcp/ip·计算机网络·tcp·bbr·通信
落羽的落羽2 小时前
【项目】JsonRpc框架——开发实现1(细节功能、字段定义、抽象层、具象层)
linux·服务器·网络·c++·人工智能·算法·机器学习
handler012 小时前
【算法】并查集(普通/扩展/带权)模板与例题
数据结构·c++·笔记·算法·c·图论·查并集
qq7422349842 小时前
从“感知”到“决断”:测评百度伐谋产业决策智能体的端到端推理与行动机制
人工智能·算法·百度·大模型·运筹优化