悬线法
以前写过求最大正方形面积的题目,这只要处理 [i-1][j],[i][j-1],[i-1][j-1] 三个位置的最小值就可以,用不到悬线法,简单的线性dp;
但是当要求最大长方形时,那种方法就不适合了,悬线法就出现了;
模板题: P4147 玉蟾宫
悬线法可以分为三个部分:
- l[i][j] 代表位置 (i,j) 可以往左扩展的最小坐标,就是最远的坐标
- r[i][j] 代表位置 (i,j) 可以往右扩展的最大坐标,就是最远的坐标
- up[i][j] 代表位置 (i,j) 可以往上扩展的最大距离,不是坐标了
l,r 数组都要进行预处理,最关键的是在进行dp时,l 数组要取最大值,r 数组要取最小值,up 数组加 1 ,就跟求最大正方形面积的思路是一样的,要保证最短的也符合条件;
代码:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=1100;
const int M=50100;
const int mod=1e9;
int n,m,a[N][N];
int l[N][N],r[N][N],up[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;cin>>c;
if(c=='F') a[i][j]=1;
up[i][j]=1,l[i][j]=r[i][j]=j;
}
}
for(int i=1;i<=n;i++){
for(int j=2;j<=m;j++){
if(a[i][j]&&a[i][j-1]) l[i][j]=l[i][j-1];
}
}
for(int i=1;i<=n;i++){
for(int j=m-1;j>=1;j--){
if(a[i][j]&&a[i][j+1]) r[i][j]=r[i][j+1];
}
}
int ans=0;
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]&&a[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]);
up[i][j]=up[i-1][j]+1;
}
ans=max(ans,(r[i][j]-l[i][j]+1)*up[i][j]);
}
}
cout<<ans*3<<endl;
return 0;
}