https://vjudge.net/problem/UVALive-3029
题意:找出最大的子矩形。
只想到了纯暴力,复杂度太高了。
白书指导用扫描法,二维的扫描法,利用周围的元素维护当前元素,很微妙了。
从上到下设为垂线,up数组记录,如果是R,记为0,否则是同列上面元素+1。
从左到右利用lef数组维护,如果是R的话记得记为小于等于0的数,免得影响后续的判断,否则为max(同列上面元素,同行最左边的R即为lo+1),从右向左维护同理。
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int atlas[1005][1005],up[1005][1005],lef[1005][1005],ri[1005][1005];
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
int w,h;
scanf("%d%d",&h,&w);
for(int i=0;i<h;i++)
for(int j=0;j<w;j++)
{
char t=getchar();
while(t!='F'&&t!='R')t=getchar();
if(t=='F') atlas[i][j]=1;
else atlas[i][j]=0;
}
int lo,ro;
for(int i=0;i<h;i++)
{
lo=-1;
for(int j=0;j<w;j++)
{
if(!atlas[i][j])
{
up[i][j]=lef[i][j]=0;
lo=j;
}
else
{
up[i][j]=i==0?1:up[i-1][j]+1;
lef[i][j]=i==0?lo+1:max(lef[i-1][j],lo+1);
}
}
}
int ans=0;
for(int i=0;i<h;i++)
{
ro=w;
for(int j=w-1;j>=0;j--)
{
if(!atlas[i][j])
{
ro=j;
ri[i][j]=h+28;
}
else
{
ri[i][j]=i==0?ro-1:min(ri[i-1][j],ro-1);
ans=max(ans,up[i][j]*(ri[i][j]-lef[i][j]+1));
}
}
}
printf("%d\n",ans*3);
}
}