• 题目链接:​​P1169 [ZJOI2007]棋盘制作​
  • 题目大意:给定一个01棋盘,求其中01交错的最大正方形与矩形。
  • 思路:悬线法
  • 求解正方形&&长方形的情况即可。题目要求01交错,所以"!="即可。
  • 参考代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 2005;
int lft[N][N], rgt[N][N], up[N][N], res[N][N];
int main() {
int n, m, ans_2 = -100, ans_1 = -100;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &res[i][j]);
lft[i][j] = rgt[i][j] = j;
up[i][j] = 1;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 2; j <= m; j++) {
if (res[i][j] != res[i][j - 1]) {
lft[i][j] = lft[i][j - 1]; //预处理左边界
}
}
for (int j = m - 1; j >= 1; j--) {
if (res[i][j] != res[i][j + 1]) {
rgt[i][j] = rgt[i][j + 1]; //预处理右边界
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i > 1 && res[i][j] != res[i - 1][j]) {
lft[i][j] = max(lft[i][j], lft[i - 1][j]);
rgt[i][j] = min(rgt[i][j], rgt[i - 1][j]);
up[i][j] = up[i - 1][j] + 1;
}
int a = rgt[i][j] - lft[i][j] + 1; //横向长度
int b = min(a, up[i][j]); //竖向长度
// printf("a:%d b:%d\n",a,b);
ans_1 = max(ans_1, b * b); //正方形
ans_2 = max(ans_2, a * up[i][j]); //长方形
// ans_2 = max(ans_2, (rgt[i][j] - lft[i][j] + 1) * up[i][j]);
}
}
printf("%d\n%d\n", ans_1, ans_2);
return 0;
}