Luogu1681_ 最大正方形II
題目背景
忙完了學校的事,v神終於可以做他的“正事”:陪女朋友散步。一天,他和女朋友走著走著,不知不覺就來到了一個千里無煙的地方。v神正要往回走,如發現了一塊牌子,牌子上有有一行小字和一張圖,小字說道:“找到圖上最大的交錯正方形之後和我聯絡,這塊地就是你的了。”在房價瘋長的年代,v神當然不願錯過這個機會,於是開始找了起來……以v神的能力當然找不出來了,你能幫v神找出來嗎?
題目描述
圖上有一個矩陣,由N*M個格子組成,這些格子由兩種顏色構成,黑色和白色。請找到面積最大的且內部是黑白交錯(即兩個相連的正方形顏色不能相同)的正方形。
輸入格式:
第一行兩個整數N和M,分別表示行數和列數。接下來有N行,每行M個數,0或1分別表示這個格子是黑色或白色。
輸出格式:
僅有一行,表示滿足條件最大正方形的 邊長
樣例
INPUT
3 3
0 1 0
1 0 0
1 1 1
OUTPUT
2
HINT
樣例解釋:
(1,1)到(2,2)這個正方形是滿足條件的,它的邊長是2
資料範圍約定:
對於30%的資料,\(N\leq20\)
對於60%的資料,\(N\leq300\)
對於100%的資料,\(N\leq1500\)
SOLUTION
題解:dp
一看資料範圍就知道是\(O(n^2)\)的演算法,再說了這題如果要暴力的話最暴力的可以達到\(O(n^6)\)之高。(有沒有其他暴力我不知道qwq)
所以考慮通過題目的性質進行優化。
根據題意,正方形的合法與否在於相鄰格子之間關係的合法與否。所以我們可以先處理左右之間關係,在處理上下之間的關係。這裡就可以用\(lft[i][j],rgt[i][j]\)
然後處理上下層之間的關係就可以直接進行層與層之間的轉移了
\[lft[i][j]=max(lft[i][j],lft[i-1][j])\]
\[rgt[i][j]=min(rgt[i][j],rgt[i-1][j])\]
\[hgt[i][j]=hgt[i-1][j]+1\]
這個\(hgt\)指的是高度(縱向長度)
然後維護過程中順帶記錄一下最大值就可以了
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int N=1510; int n,m,hgt[N][N],sq[N][N],lft[N][N],rgt[N][N]; int main(){ int i,j; scanf("%d%d",&n,&m); for (i=1;i<=n;++i) for (j=1;j<=m;++j){ scanf("%d",&sq[i][j]); lft[i][j]=j;rgt[i][j]=j;hgt[i][j]=1; } for (i=1;i<=n;++i) for (j=2;j<=m;++j) if (sq[i][j]^sq[i][j-1]) lft[i][j]=lft[i][j-1]; for (i=1;i<=n;++i) for (j=m-1;j>=1;--j) if (sq[i][j]^sq[i][j+1]) rgt[i][j]=rgt[i][j+1]; int ans=0; for (i=1;i<=n;++i) for (j=2;j<=m;++j){ if (i>1&&(sq[i][j]^sq[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]); hgt[i][j]=hgt[i-1][j]+1; } int a=min(rgt[i][j]-lft[i][j]+1,hgt[i][j]); ans=max(ans,a); } printf("%d\n",ans); return 0; }