P4147 玉蟾宫

玉蟾宫

题目

题目背景

有一天,小猫 rainbow 和 freda 来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。

题目描述

这片土地被分成 N × M N\times M N×M 个格子,每个格子里写着 ‘R’ 或者 ‘F’,R 代表这块土地被赐予了 rainbow,F 代表这块土地被赐予了 freda。

现在 freda 要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着 ‘F’ 并且面积最大。

但是 rainbow 和 freda 的 OI 水平都弱爆了,找不出这块土地,而蓝兔也想看 freda 卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为 S S S,它们每人给你 S S S 两银子。

输入格式

第一行两个整数 N N N M M M,表示矩形土地有 N N N M M M 列。

接下来 N N N 行,每行 M M M 个用空格隔开的字符 ‘F’ 或 ‘R’,描述了矩形土地。

输出格式

输出一个整数,表示你能得到多少银子,即 ( 3 × 最大 ’F’ 矩形土地面积 3\times \text{最大 'F' 矩形土地面积} 3×最大 ’F’ 矩形土地面积) 的值。

样例 #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 ≤ 200 1 \leq N, M \leq 200 1N,M200
对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 1000 1 \leq N, M \leq 1000 1N,M1000


题解

本题使用悬线法
悬线法,顾名思义,是统计了每个节点向上所能扩展的最大值。这里记为 up数组。
同时,我们还要统计每个点向左和向右所能扩展的最大值,这里记为 le数组和 ri 数组。
对于每个 le[i][j] , ri[i][j] 和 up[i][j],如果 i >1,那么可以得出递推式:

	le[i][j] = max(le[i][j], le[i-1][j]);
	ri[i][j] = min(ri[i][j], ri[i-1][j]);
	up[i][j] += up[i-1][j];

这样我们就可以很轻松地解决这道题了。

Code:

#include <iostream>
#include <algorithm> 
#include <cstring> 
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
const int mod = 10007;
int n, m, ans;
int le[maxn][maxn], ri[maxn][maxn], up[maxn][maxn];
char maze[maxn][maxn];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++) {
			cin >> maze[i][j];
			le[i][j] = ri[i][j] = j;//别忘了初始化
			up[i][j] = 1;
		}
	for(int i = 1; i <= n; i++)
		for(int j = 2; j <= m; j++) {
			if(maze[i][j] == 'F' && maze[i][j-1] == 'F') {
				le[i][j] = le[i][j-1];//将l数组向左初始化
			}
		}
	for(int i = 1; i <= n; i++)
		for(int j = m-1; j >= 1; j--) {
			if(maze[i][j] == 'F' && maze[i][j+1] == 'F') {
				ri[i][j] = ri[i][j+1];//将r数组向右初始化
			}
		}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++) {
			if(maze[i][j] != 'F') continue;
			if(i > 1 && maze[i-1][j] == 'F') {//满足条件,调整le和ri
				le[i][j] = max(le[i][j], le[i-1][j]);
				ri[i][j] = min(ri[i][j], ri[i-1][j]);
				up[i][j] += up[i-1][j];
			}
			ans = max(ans, (ri[i][j] - le[i][j] + 1) * up[i][j]);//长乘宽计算面积
		}
	cout << ans*3;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值