本题就是要求最大子矩阵--
思路: 1.针对于dp数组中代表的每一个点,我们为其设置它的高度h。
当这个点是障碍时,我们把它的高度设置为0,否则它的高度是垂直方向的上一个点加1。
2.我们设法求出该点向左和向右能够延伸的最大距离。然后用right - left + 1就等于边的长度。
3.我们用高乘以边得到面积,通过判断后找到最大的面积,就可以得到答案了。
如何表示高度: 在输入的时候就行判断,然后对dp数组进行初始化。如果是F,则h[i][j] = h[i-1][j] + 1,否则h[i][j] = 0。
如何表示宽度: 我们按行进行遍历,对于第i行的点,分别为它们设置下标对应的l,r数组进行表示left,right。
以找左边最大延伸距离为例:当向左边延伸的时候,我们判断该点的左边的点的高度,如果左边点 的高度大于等于该点的高度,说明这个点是可以延伸到的,所以我们继续向该点的下一个点进行延 伸。
for(int j = 1; j <= N; j++){
while(h[i][l[j]-1] >= h[i][j]){
l[j] = l[l[j]-1];
}
}
借用的代码:
#include<stdio.h>
#include<string.h>
/*
2
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
5 5
R R R R R
R R R R R
R R R R R
R R R R R
R R R R R
*/
int h[1100][1100],l[1100],r[1100];
int main()
{
int K,M,N;
char ch[4];
scanf("%d",&K);
while(K--)
{
memset(h,0,sizeof(h));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
scanf("%d%d",&M,&N);
for(int i = 1; i <= M; i++)
{
for(int j = 1; j <= N; j++)
{
scanf("%s",ch);
if(ch[0] == 'F')
h[i][j] = h[i-1][j] + 1;
else
h[i][j] = 0;
}
}
__int64 MaxArea = -0xffffff0;
for(int i = 1; i <= M; i++)
{
for(int j = 1; j <= N; j++)
l[j] = r[j] = j;
l[0] = 1;
r[N+1] = N;
h[i][0] = -1;
h[i][N+1] = -1;
for(int j = 1; j <= N; j++)
{
//如果收它左边的点的高度大于等于它,就将它们对于的左值赋值为左边那个点,这样可以保证合适的最左点
while(h[i][l[j]-1] >= h[i][j]){
l[j] = l[l[j]-1];
}
}
//寻找最右点
for(int j = N; j >= 1; j--)
{
while(h[i][r[j]+1] >= h[i][j])
r[j] = r[r[j]+1];
}
for(int j = 1; j <= N; j++)
{
if(h[i][j]*(r[j]-l[j]+1) > MaxArea)
MaxArea = h[i][j]*(r[j]-l[j]+1);
}
}
printf("%I64d\n",MaxArea*3);
}
return 0;
}