此题最要考查的知识点主要是扫描法和递推;
此题如果用普通的枚举的话,那结果肯定是超时的,所以必须另想他法。最后我选择了用:扫描法(从上到下的扫描);
这样,每个格子(i,j)对应着一个以第i行为下界,高度为up(i,j),左右边界分别为left(i,j)和right(i,j)的矩形。不难发现所有矩形中面积最大的矩形即为所求的。
当当前的点不是空格时,3个数组均为0,否则up(i,j)=up(i-1,j)+1(向下扩展); 而left(i,j)=max{left(i-1,j),lo+1}(left(i-1,j)记录的是前面可以组成矩形的最大值),同理,right(i,j)=min{right(i-1,j),ro-1} ;具体的过程自己看下面的代码吧!!!!
#include <stdio.h>
#include <string.h>
#define max(a,b)(a>b?a:b)
#define min(a,b)(a<b?a:b)
const int MAX = 1000 + 2;
int mat[MAX][MAX],up[MAX][MAX],left[MAX][MAX],right[MAX][MAX];
int main()
{
freopen("Input.txt","r",stdin);
int T,i,j,n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i = 0;i < n;i++)
for(j = 0;j < m;j++){
char ch = getchar();
while(ch != 'F'&&ch != 'R') ch = getchar();
mat[i][j] = ch == 'F' ? 0 : 1;
}
int ans = 0;
for(i = 0;i < n;i++){
int lo = -1,ro = m;
for(j = 0;j < m;j++)
{
if(mat[i][j] == 1){
lo = j; //此时标记的点位障碍点
up[i][j] = left[i][j] = 0; //up为了此处起重新开始,left为了max时排除此点
}else
{
up[i][j] = i == 0 ? 1 : up[i-1][j]+1; //此处注意
left[i][j] = i == 0 ? lo + 1 : max(lo+1,left[i-1][j]); //i==0时没有前一行
}
}
for(j = m-1;j >= 0;j--)
{
if(mat[i][j] == 1){
right[i][j] = m;
ro = j;
}else
{
right[i][j] = i == 0 ? ro - 1 : min(ro-1,right[i-1][j]);
ans = max(ans,up[i][j]*(right[i][j]-left[i][j]+1));
}
}
}
printf("%d\n",ans*3);
}
return 0;
}