bzoj1057: [ZJOI2007]棋盘制作--最大子矩阵
既然要求最大01子矩阵,那么把应该为0的位置上的数取反,这样就变成求最大子矩阵
最大子矩阵可以用单调栈
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define maxn 2005 5 using namespace std; 6 int n,m,map[maxn][maxn],ans1,ans2,l[maxn],r[maxn],d[maxn],t; 7 8 int main(){ 9 scanf("%d%d", &n, &m); 10 for (int i=1; i<=n; i++) 11 for (int j=1; j<=m; j++){ 12 scanf("%d", &map[i][j]); 13 if ((i+j)&1) map[i][j]^=1; 14 } 15 for (int i=1; i<=n; i++){ //黑为奇数行列 16 for (int j=1; j<=m; j++){ 17 l[j]=r[j]=j; 18 if (map[i][j]) d[j]++; 19 else d[j]=0; 20 } 21 for (int j=1; j<=m; j++) if (d[j]) while (d[l[j]-1]>=d[j]) l[j]=l[l[j]-1]; 22 for (int j=m; j>=1; j--) if (d[j]) while (d[r[j]+1]>=d[j]) r[j]=r[r[j]+1]; 23 for (int j=1; j<=m; j++){ 24 t=min(d[j],r[j]-l[j]+1); 25 ans1=max(ans1,t*t); 26 ans2=max(ans2,d[j]*(r[j]-l[j]+1)); 27 } 28 } 29 memset(d,0,sizeof(d)); 30 for (int i=1; i<=n; i++){ //白为奇数行列 31 for (int j=1; j<=m; j++){ 32 l[j]=r[j]=j; 33 if (!map[i][j]) d[j]++; 34 else d[j]=0; 35 } 36 for (int j=1; j<=m; j++) if (d[j]) while (d[l[j]-1]>=d[j]) l[j]=l[l[j]-1]; 37 for (int j=m; j>=1; j--) if (d[j]) while (d[r[j]+1]>=d[j]) r[j]=r[r[j]+1]; 38 for (int j=1; j<=m; j++){ 39 t=min(d[j],r[j]-l[j]+1); 40 ans1=max(ans1,t*t); 41 ans2=max(ans2,d[j]*(r[j]-l[j]+1)); 42 } 43 } 44 printf("%d\n%d\n", ans1, ans2); 45 return 0; 46 }