luogu P1169 [ZJOI2007]棋盘制作
最大子矩阵
这题两问
1.最大子正方形
2.最大子矩阵
对于最大子矩阵有几个东东:
1.l[i][j]:i,j这个点向左拓展能到的最远点
2.r[i][j]:i,j这个点向右拓展能到的最远点
3.u[i][j]:i,j这个点向上能拓展几格
就可以愉快地计算了!
std:
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int n,m;
int l[N][N]={0},r[N][N]={0},u[N][N]={0},s[N][N]={0};
int ans1=0,ans2=0;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&s[i][j]);
l[i][j]=j;
r[i][j]=j;
u[i][j]=1;
}
}
for(int i=1;i<=n;i++){//悬线法计算l,r,u
for(int j=2;j<=m;j++){
if(s[i][j]!=s[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(s[i][j]!=s[i][j+1]) r[i][j]=r[i][j+1];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i>1&&s[i][j]!=s[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]);
u[i][j]=u[i-1][j]+1;
}
int a=r[i][j]-l[i][j]+1;
int b=min(a,u[i][j]);
ans1=max(ans1,b*b);
ans2=max(ans2,a*u[i][j]);
}
}
printf("%d\n%d\n",ans1,ans2);
return 0;
}