方法一
- 黑白棋盘拥有性质:(r + c) % 2的值决定颜色
- 因此把某色全部反转,直接求另一色的最大矩形即可,单调栈的经典问题
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 2005;
int n, m, a[maxn][maxn], h[maxn][maxn];
int ans1, ans2;
void solve(int c) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
h[i][j] = (a[i][j] == c) ? h[i][j - 1] + 1 : 0;
}
}
int L[n + 5], R[n + 5];
for (int j = 1; j <= m; j++) {
vector<int> st;
for (int i = 1; i <= n; i++) {
while (st.size() && h[st.back()][j] >= h[i][j]) st.pop_back();
L[i] = st.size() ? st.back() + 1 : 1;
st.emplace_back(i);
}
st.clear();
for (int i = n; i; i--) {
while (st.size() && h[st.back()][j] >= h[i][j]) st.pop_back();
R[i] = st.size() ? st.back() - 1 : n;
st.emplace_back(i);
}
for (int i = 1; i <= n; i++) {
int S = h[i][j] * (R[i] - L[i] + 1);
int t = min(h[i][j], R[i] - L[i] + 1);
ans1 = max(ans1, t * t);
ans2 = max(ans2, S);
}
}
}
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 + j) & 1)
a[i][j] ^= 1;
}
solve(0), solve(1);
return !printf("%d\n%d\n", ans1, ans2);
}
方法二
- 悬线法:对每个点求出它合法的矩阵向左向右向上分别能多长,然后更新答案。其中求时肯定不能暴力,要从上一个递推过来
- 如果高度能从上面递增过来,左右线也要跟上面取min
- 其实我觉得和方法一思想挺像的……
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 2005;
int n, m, a[maxn][maxn];
int h[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
int ans1, ans2;
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]);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i > 1 && a[i][j] != a[i][j - 1]) {
l[i][j] = l[i][j - 1] + 1;
} else l[i][j] = 1;
}
for (int j = m; j; --j) {
if (j < m && a[i][j] != a[i][j + 1]) {
r[i][j] = r[i][j + 1] + 1;
} else r[i][j] = 1;
}
for (int j = 1; j <= m; j++) {
if (i > 1 && a[i][j] != a[i - 1][j]) {
h[i][j] = h[i - 1][j] + 1;
l[i][j] = min(l[i][j], l[i - 1][j]);
r[i][j] = min(r[i][j], r[i - 1][j]);
} else h[i][j] = 1;
int Len = r[i][j] + l[i][j] - 1;
int t = min(Len, h[i][j]);
ans1 = max(ans1, t * t);
ans2 = max(ans2, Len * h[i][j]);
}
}
return !printf("%d\n%d\n", ans1, ans2);
}