给出一个 \(N * M\) 的 \(01\) 矩阵, 求最大的正方形和最大的矩形交错子矩阵
\(n , m \leq 2000\)ios
悬线法能够求出给定矩阵中知足条件的最大子矩阵spa
对于每一个点, 维护 两条等长的线段, 两线段的底部达到此点的纵坐标, 分别表明能从这个点达到的最左 / 最右端点
大概长这样code
l r | | | | | | | | | * |
那么枚举每一个点的这两条线段, 不断用 \((r - l + 1) * dis\) 更新答案便可
这就是悬线法继承
这两条线段看上去很难维护, 其实否则
由于其等长, 咱们将这两条线段用以下几个属性表示:
\(l[i][j]\) 表示从 \((i, j)\) 能达到的最左的坐标
\(r[i][j]\) 表示从 \((i, j)\) 能达到的最右的坐标
\(up[i][j]\) 表示 以 \((i, j)\) 向上达到的 最上坐标, 即悬线的长度get
初始化知足条件的每一个\(1 * 1\) 小矩阵 \(l[i][j] = r[i][j] = j, up[i][j] = 1\), 即围成一个 \(1 * 1\) 的小小矩形string
容易想到维护悬线能够递推, 在知足矩阵限制的条件下, 先初始化
\[l[i][j] = l[i][j - 1]\] \[r[i][j] = r[i][j + 1]\]it
比对上一行,在知足矩阵限制的条件下, 咱们只能取最窄知足条件
\[l[i][j] = max(l[i][j], l[i - 1][j])\] \[r[i][j] = min(r[i][j], r[i - 1][j])\]
而后悬线长度能够继承上一行的 \[up[i][j] = up[i - 1][j] + 1\]io
有了悬线直接计算围出来的面积便可class
此题求最大交错矩阵
交错矩阵任意相邻两格颜色不一样
因而限制条件即为相邻两格颜色不等
放个代码理解 悬线法stream
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<climits> #define LL long long #define REP(i, x, y) for(int i = (x);i <= (y);i++) using namespace std; int RD(){ int out = 0,flag = 1;char c = getchar(); while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();} while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();} return flag * out; } const int maxn = 2019; int lenx, leny; int map[maxn][maxn]; int l[maxn][maxn], r[maxn][maxn]; int up[maxn][maxn]; int ans1, ans2; void init(){ lenx = RD(), leny = RD(); REP(i, 1, lenx)REP(j, 1, leny){ map[i][j] = RD(); l[i][j] = r[i][j] = j; up[i][j] = 1; } REP(i, 1, lenx)REP(j, 2, leny){ if(map[i][j] != map[i][j - 1])l[i][j] = l[i][j - 1];//预处理左边界 } REP(i, 1, lenx)for(int j = leny - 1;j >= 1;j--){ if(map[i][j] != map[i][j + 1])r[i][j] = r[i][j + 1];//右边界 } } void solve(){ REP(i, 1, lenx)REP(j, 1, leny){ if(i > 1 && map[i][j] != map[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]); up[i][j] = up[i - 1][j] + 1; } int a = r[i][j] - l[i][j] + 1;//宽 int b = min(a, up[i][j]); ans1 = max(ans1, b * b); ans2 = max(ans2, a * up[i][j]); } printf("%d\n%d\n", ans1, ans2); } int main(){ init(); solve(); return 0; }