最大纯矩阵

洛谷P4147

2
做法:设 \(l_{i,j}\) 表示 \(i,j\) 一直往左走直到走不通的 \(F\) 的纵坐标, \(r_{i,j}\) 表示 \(i,j\) 一直往右走直到走不通的 \(F\) 的纵坐标, \(h_{i,j}\) 表示 \(i,j\) 一直向上走直
大小到走不通的距在1

\(l ~,~ r ~,~h\) 都很好求。

然后我们怎么算呢?对于一个点 \(i,j\) ,我们要算的是以第 \(i\) 行为底,底边包含 \(i,j\),高为 \(h_{i,j}\) 的最大矩形。实际情况中,也许会出现“凸”字形的情况,这时位于“凸”的肚子上的点,它们要算的矩形的 \(l\)\(r\) 并不是它自己的 \(l\)\(r\) ,所以要从它上面的点更新 \(l\)\(r\) 。这样做是没问题的,因为一列中下面的点肯定要考虑所有上面点的限制,而且我们从上往下遍历, \(l\)\(r\) 被更改了肯定对正确性是没有影响的。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
bool mp[N][N];
int l[N][N], r[N][N], h[N][N];
int n, m;
int res;
char v;
inline int read()
{
	int x = 0;
	while(!isdigit(v)) v = getchar();
	while(isdigit(v)) x = (x << 1) + (x << 3) + v - 48, v = getchar();
	return x;
}
int main()
{
	n = read(); m = read();
	for(int i = 1; i <= n; ++i)
	    for(int j = 1; j <= m; ++j)
	    {
	    	while((v ^ 'R') && (v ^ 'F')) v = getchar();
	    	mp[i][j] = (v ^ 'R') ? true : false;
			v = getchar();
		} 
	
	for(int i = 1 ; i <= n; ++i)
	    for(int j = 1; j <= m; ++j)
	        if(mp[i][j])
	        {
	        	if(mp[i][j - 1])
	        	    l[i][j] = l[i][j - 1];
	        	else
	        	    l[i][j] = j;
			}
	
	for(int i = 1; i <= n; ++i)
	    for(int j = m; j; --j)
	        if(mp[i][j])
	        {
	        	if(mp[i][j + 1])
	        	    r[i][j] = r[i][j + 1];
	        	else r[i][j] = j;
			}
	
	for(int i = 1; i <= n; ++i)
	    for(int j = 1; j <= m; ++j)
	        if(mp[i][j])
	        {
	        	h[i][j] = h[i - 1][j] + 1;
	        	if(mp[i - 1][j])
	        	{
	        		l[i][j] = max(l[i][j], l[i - 1][j]);
	        		r[i][j] = min(r[i][j], r[i - 1][j]); //此处更新l,r
				}
				res = max(res, (r[i][j] - l[i][j] + 1) * h[i][j]);
			}
	
	cout << 3 * res;
	return 0;
}
posted @ 2022-04-09 11:30  Faker_yu  阅读(33)  评论(0)    收藏  举报