P4147 玉蟾宫 题解
给定一个 的矩阵,找出最大矩形,满足所有元素为 F
,输出这个矩形的大小 。
悬线法。
用 记录悬线长度,每个矩形的高一定是一个悬线。接下来用 和 记录悬线左右最远能到的位置,求 方法如下:
- 数组:初始化为 。对于所有的 ,如果 且 ,那么 。
- 数组:初始化为当前列。如果 ,且 ,那么 可以往左扩展,。
- 数组:初始化为当前列。采用倒序循环,如果 ,且 ,那么 可以往右拓展,。
其中 和 记录的是悬线左右最远能到的位置,那么我们就要处理这种情况:
其中按照如上方式更新 ,那么第四列里都是 ,无法正确计算右边的悬线为高时的矩形的面积,因此我们需要再更新一次 和 数组。当存在悬线时,悬线上的 保持相同,应均为原来的最小值。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
char a[1005][1005];
int l[1005][1005], r[1005][1005], h[1005][1005];
int ans;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
// 初始化
h[i][j] = 1;
l[i][j] = j, r[i][j] = j;
}
}
for (int i = 1; i <= n; i++) {
// 求 l 和 r
for (int j = 2; j <= m; j++) {
if (a[i][j] == 'F' && a[i][j - 1] == 'F') {
l[i][j] = l[i][j - 1];
}
}
for (int j = m - 1; j >= 1; j--) {
if (a[i][j] == 'F' && a[i][j + 1] == 'F') {
r[i][j] = r[i][j + 1];
}
}
// 更新 l 和 r
if (i > 1) {
for (int j = 1; j <= m; j++) {
if (a[i][j] == 'F' && a[i - 1][j] == 'F') {
if (l[i - 1][j] > l[i][j]) {
l[i][j] = l[i - 1][j];
}
if (r[i - 1][j] < r[i][j]) {
r[i][j] = r[i - 1][j];
}
}
}
}
}
// 求 h
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j] == 'F' && a[i - 1][j] == 'F') {
h[i][j] = h[i - 1][j] + 1;
}
}
}
// 统计答案,枚举所有悬线为高时的情况
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j] == 'F') {
ans = max(ans, (r[i][j] - l[i][j] + 1) * h[i][j]);
}
}
}
cout << ans * 3 << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本