給出一個 \(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; }