懸線法
以前寫過求最大正方形面積的題目,這隻要處理 [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;
}