P4147 玉蟾宫(最大子矩形)

思路

可以利用悬线法,处理对于每个点在高度为 \(h\) 时的左右边界,然后随着高度增加,这个边界表示的范围一定是单调不增的,但是高度又在增加,所以一直取 \(max\) 就对了

最后注意输出答案的三倍
\(C++\) \(AC\) \(Code:\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
int l[MAXN][MAXN], r[MAXN][MAXN], h[MAXN][MAXN]; //分别存放位于点 (i, j) 时的高度为 h 的 左右边界
char mapp[MAXN][MAXN];
int n, m;
void init() {
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			l[i][j] = r[i][j] = j, h[i][j] = 1; // 初始化边界为自身,高度为1
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			cin >> mapp[i][j];
	init();
	for (int i = 1; i <= n; ++i) {
		for (int j = 2; j <= m; ++j)
			if (mapp[i][j] == 'F' && mapp[i][j - 1] == 'F')
				l[i][j] = l[i][j - 1]; // 尝试向左扩展边界
		for (int j = m - 1; j >= 1; --j)
			if (mapp[i][j] == 'F' && mapp[i][j + 1] == 'F')
				r[i][j] = r[i][j + 1]; // 尝试向右扩展边界
	}
	int ans = 0;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j) {
			if (mapp[i][j] == 'R')
				continue;
			if(mapp[i - 1][j] == 'F') { // 更新高度增加时的左右边界
				h[i][j] = h[i - 1][j]  + 1;
				l[i][j] = max(l[i][j], l[i - 1][j]);
				r[i][j] = min(r[i][j], r[i - 1][j]);
			}
			ans = max(ans, (r[i][j] - l[i][j] + 1) * h[i][j]); // 求面积最大值
		}
	cout << ans * 3;
	return 0;
}
posted @ 2025-10-12 09:44  孤独的Bochi  阅读(11)  评论(0)    收藏  举报