题目大意
给定一个m*n的矩阵,其中一些池子是空地,其他事障碍,求出最大的空地面积并将结果乘以三。
分析
最常用的方法暴力枚举,枚举矩形的两个顶角坐标。,然后判断求面积,复杂度十分大,对于本题目的数据显然通过不了,我们采用扫描发法,把每个格子向上的连续空格看作一个悬线,并且用up(i,j),left(i,j),right(i,j分别表示可以向上的悬线长度,向左向右的最大边界,注意边界保留的是空地的下标,不是障碍的下标。这样的话每一个格子对应了以i行位下界,高度为up(i,j)左右边界分别是left(i,j)和right(i,j)的矩形,不难发现这些矩形中的最大面积就是所求。
那么这几个量如何更新呢
首先 如果当前格子不是障碍 up(i,j)=i==0?1:up(i-1,j)+1;
否则 up(i,j)=0;
left(i,j)=max(left(i-1,j),lo+1); lo是最左的障碍,初始为-1
right(i,j)=min{right(i-1,j),ro-1} ro是最右的障碍,初始为n
上代码
#include<iostream>
#include<algorithm>
#define maxn 1000+10
using namespace std;
int le[maxn][maxn], ri[maxn][maxn], up[maxn][maxn];
int q[maxn][maxn];
int lo, ro;
int main()
{
int T;
cin >> T;
while (T--)
{
int n, m;
cin >> m >> n;
int ans = 0;
char ch;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
{
cin >> ch;
if (ch == 'F') q[i][j] = 1; //障碍为0,空地为1
else if (ch == 'R') q[i][j] = 0;
}
/*for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << q[i][j]<<" ";
cout << endl;
}*/
for (int i = 0; i < m; i++)
{
lo =-1, ro = n;
for (int j = 0; j < n; j++) //更新up(i,j)和lo(i,j)
{
if (q[i][j])
{
up[i][j] = i == 0 ? 1 : up[i - 1][j]+1;
le[i][j] = i == 0 ? lo+1 : max(lo + 1, le[i - 1][j]);
}
else
{
up[i][j] = le[i][j] = 0;
lo = j;
}
}
for (int j = n - 1; j >= 0; j--)
{
if (q[i][j])
{
ri[i][j] = i == 0 ? ro-1 : min(ro-1, ri[i - 1][j]);
ans = max(ans, up[i][j] * (ri[i][j] - le[i][j] + 1));
}
else
ro = j, ri[i][j] = n;
}
}
cout << ans * 3 << endl;
}
return 0;
}