題目描述:在乙個m * n的矩陣中,所有的元素只有0和1,從這個矩陣中找出乙個面積最大的全1子矩陣,所謂最大是指元素1的個數最多。
輸入:輸入可能包含多個測試樣例。
對於每個測試案例,輸入的第一行是兩個整數m、n(1<=m、n<=1000):代表將要輸入的矩陣的大小。
矩陣共有m行,每行有n個整數,分別是0或1,相鄰兩數之間嚴格用乙個空格隔開。
輸出:對應每個測試案例,輸出矩陣中面積最大的全1子矩陣的元素個數。
樣例輸入:
2 2樣例輸出:0 4解題思路:**自0 00 0
4 40 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
方法是:
1、先將0/1矩陣讀入x,對每乙個非零元素x[i][j],將其更新為:在本行,它前面的連續的1的個數+1(+1表示算入自身)
比如,若某一行為0 1 1 0 1 1 1,則更新為0 1 2 0 1 2 3
2、對每乙個非零元素x[i][j],在第j列向上和向下掃瞄,直到遇到比自身小的數,若掃瞄了y行,則得到乙個大小為x[i][j]*(y+1)的全1子矩陣(+1表示算入自身所在行)
比如,若某一列為[0 3 4 3 5 2 1]'(方便起見,這裡將列表示成乙個列向量),我們處理這一列的第4個元素,也就是3,它向上可以掃瞄2個元素,向下可以掃瞄1個元素,於是得到乙個4×3的全1子矩陣。
3、在這些數值中取乙個最大的。
思想大概如下圖所示(空白處的0沒有標出)
對照步驟2中給出的例子,藍色的箭頭表示向上向下掃瞄,黑色的框表示最終得到的全1子矩陣
這樣做為什麼是對的?
想一想,對那個最大的全1子矩陣,用這種方法能不能找到它呢?——肯定可以。
乙個最大全1子矩陣,肯定是四個邊界中的每乙個都不能再擴充套件了,如下圖
假設圖中全1子矩陣就是最大子矩陣,則左邊界左側那一列肯定有乙個或多個0(否則就可以向左邊擴充套件一列,得到乙個更大的全1矩陣)
對其他3個邊界有類似的情況。
然後看圖中用黑圈標出的1(其特點是:和左邊界左側的某個0在同一行),從這個1出發,按照之前的方法,向上向下掃瞄,就可以得到這個子矩陣。所以,肯定可以找到。
下面是我的**,實際實現的時候,為了提高效率,估計了一下upperbound,這個upperbound就是:在當前列,
包含x[i][col]的連續的非零序列的和,比如對某列[0 3 4 3 5 2 1]',後面6個的upperbound都是
3 + 4 + 3 + 5 + 2 + 1 = 18,對於0元素,不需要upperbound
1 #include2view codeusing
namespace
std;34
intmain()517
}18//prepare:
19for(int i=0;i)23}
24//
計算upperbound
25for(int j=0;j)
34for(int k=i;k)
37 i=temp;38}
39} 40}
4142
int maxarea=0;43
for(int i=0;i)
52for(int row=i+1;row)
57if(cnt*val>maxarea)maxarea=cnt*val;58}
59}60}
61 cout<
63return0;
6465 }
九度 1497 面積最大的全1子矩陣
題目描述 在乙個m n的矩陣中,所有的元素只有0和1,從這個矩陣中找出乙個面積最大的全1子矩陣,所謂最大是指元素1的個數最多 leetcode 原題,沒有案例就是跪,wa 到沒脾氣 未通過九度測試 include include include include include using names...
面積最大的全1子矩陣
題目描述 在乙個m n的矩陣中,所有的元素只有0和1,從這個矩陣中找出乙個面積最大的全1子矩陣,所謂最大是指元素1的個數最多。輸入 輸入可能包含多個測試樣例。對於每個測試案例,輸入的第一行是兩個整數m n 1 m n 1000 代表將要輸入的矩陣的大小。矩陣共有m行,每行有n個整數,分別是0或1,相...
ACM整理(四) 1497面積最大的全1子陣
程式設計思想 本質為計算直方圖中最小長方形面積 設立三個陣列,h,l,r 陣列h i 代表從當前行向上的直方圖的第i列有多少個1,有0間隔即不算 陣列l i 代表大於等於h i 個1的列最小標號為多少 陣列r i 代表大於等於h i 個1的列最大標號為多少 算完這三個陣列之後,迴圈j次 用公式h i...