題意:給定乙個01矩陣,求:
1.最大全0正方形面積
2.最大全0子矩陣面積
-----------------------------------------我是分割線-----------------------------------------
對於第一問,我們有o(nm)的動態規劃解法:
設f[i][j]表示以i,j為右下角的最大正方形邊長
正確性可以自己yy一下
對於第二問有許多o(nm)的奇怪解法,具體可以參照2023年福州第三中學王知昆的**《**用極大化思想解決最大子矩陣問題》。
我只會懸線法,還有二維單調棧解法orz
令h[i][j]表示點(i,j)向上最大延伸高度,可以想象為一根在(i,j-h[i][j]+1)到(i,j)的一根懸線,可以證明,最大子矩陣是某一根懸線的向左右盡量擴張而形成的
令l[i][j]表示i,j懸線向左最大擴充的位置,r[i][j]表示i,j懸線向右最大擴充的位置,那麼max(h[i][j]*(r[i][j]-l[i][j]+1))就是答案。
現在我們要做到o(nm)處理出h,l,r陣列
h陣列顯然可以簡單遞推。
關於l[i][j],設其初值為j,考慮能否擴張到j-1及其擴張範圍,顯然如果h[i][j]<=h[i][j-1]則可以,否則不行,如果可以那麼l[i][j]=l[i][l[i][j-1]],否則就此停止;
現在考慮能否再次擴張,再進行比較h值,將之前的j-1換成l[i][j]-1即可
r陣列同理。
為什麼這個遞推是o(nm)的呢?
顯然行與行無關,我們只考慮一行內;
把l陣列看成樹結構,則l的指向即為連向父節點的邊;
如果擴張一次完成,則新節點(j)的深度為(j-1)深度+1,這種事件出現次數<=m
每次擴張的比較過程如果成功,則深度會至少減少1,每次減少深度事件複雜度為o(1)
深度減少事件發生次數<=深度++次數<=m
所以每行內遞推複雜度為o(m)
總複雜度o(nm)徵畢。
至此,整個問題解決。
因為行與行無關,l與r可以只記錄本行內,而h陣列可以用滾動陣列,故只需開一維即可,意義不變。
**:
#includeusing namespace std;
const int maxn = 2017;
int a[maxn][maxn];
int h[maxn],l[maxn],r[maxn];
int n,ans;
int main()
for(int j=n;j>=1;j--)
{ r[j]=j;
while(r[j]
1159 最大全0子矩陣
f i,j 表示以 i,j 為右下角的最大全0子矩陣的邊長 若a i j 1,f i,j 0 否則 f i,j min 1 這樣求得的是最大全0正方形子矩陣 要求長方形矩陣,上述思路行不通 假設以 i,j 為右下角的最大矩陣 12 它可能是3 4 4 3 2 6 6 2 1 12 12 1 按上述思...
codevs 1159 最大全0子矩陣
時間限制 1 s 空間限制 128000 kb 題目描述 description 在乙個0,1方陣中找出其中最大的全0子矩陣,所謂最大是指o的個數最多。輸入描述 input description 輸入檔案第一行為整數n,其中1 n 2000,為方陣的大小,緊接著n行每行均有n個0或1,相鄰兩數間嚴...
codevs1159 最大全0子矩陣
題目描述 description 在乙個0,1方陣中找出其中最大的全0子矩陣,所謂最大是指o的個數最多。輸入描述 input description 輸入檔案第一行為整數n,其中1 n 2000,為方陣的大小,緊接著n行每行均有n個0或1,相鄰兩數間嚴格用乙個空格隔開。輸出描述 output des...