求最大的x矩阵的面积
h[maxn][maxn]记录该位置向上最多扩展的位置
初始化:第0行全置位0
更新: h[i][j] = a[i][j]==x?h[i - 1][j]+1:0;
l[maxn][maxn], r[maxn][maxn];记录向左/右最先到达不是x的位置
tmp记录上一次不为x的位置的列号
初始化:将l[][]的第0行全置位0,r[][]的第0行全置位m+1
更新:如果当前位置是x, 则l[i][j] = max(l[i - 1][j], tmp), r[i][j] = min(r[i - 1][j], tmp)
反之,将tmp置位该位置的列号,该位置的值置为l[i][j] = 0,r[i][j] = m + 1(为了不对下面的行产生影响)
*********************************************************************************************************************
面积计算,该位置:
若是最大矩阵:(r[i][j]-l[i][j]-1) * h[i][j]
若是最大正方形:min(r[i][j]-l[i][j]-1, h[i][j]) * min(r[i][j]-l[i][j]-1, h[i][j])
*********************************************************************************************************************
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 2010; int a[maxn][maxn]; int h[maxn][maxn], l[maxn][maxn], r[maxn][maxn]; int n, m; int ans1, ans2; void solve(bool x);//求最大的x矩阵 int main() { scanf("%d %d", &n, &m); for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) { scanf("%d", &a[i][j]); if((i&1)!=(j&1)) a[i][j] = !a[i][j];//按此方法将问题转化 } ans1 = ans2 = 0; solve(1); solve(0); printf("%d\n%d\n", ans1, ans2); return 0; } void solve(bool x) { //初始化 int i, j; for(i = 0; i <= m; ++i) { h[0][i] = 0; l[0][i] = 0; r[0][i] = m + 1; } for(i = 1; i <= n; ++i) { for(j = 1; j <= m; ++j) h[i][j] = a[i][j]==x?h[i - 1][j]+1:0; int tmp = 0;//初始认为向左初次达到不是x的位置是0; for(j = 1; j <= m; ++j) if(a[i][j]==x) l[i][j] = max(l[i - 1][j], tmp); else l[i][j] = 0, tmp = j;//将不满足情况的l[i][j]=0,使其不对下一行产生影响 tmp = m + 1;//初始认为向右初次达到不是x的位置是m+1; for(j = m; j; --j) if(a[i][j]==x) r[i][j] = min(r[i - 1][j], tmp); else r[i][j] = m + 1, tmp = j; for(j = 1; j <= m; ++j) { int tmp = r[i][j]-l[i][j]-1; ans2 = max(ans2, tmp*h[i][j]); int minn = min(tmp, h[i][j]); ans1 = max(ans1, minn*minn); } } }