- 題目描述:
-
在一個M * N的矩陣中,所有的元素只有0和1,從這個矩陣中找出一個面積最大的全1子矩陣,所謂最大是指元素1的個數最多。
- 輸入:
-
輸入可能包含多個測試樣例。
對於每個測試案例,輸入的第一行是兩個整數m、n(1<=m、n<=1000):代表將要輸入的矩陣的大小。
矩陣共有m行,每行有n個整數,分別是0或1,相鄰兩數之間嚴格用一個空格隔開。
- 輸出:
-
對應每個測試案例,輸出矩陣中面積最大的全1子矩陣的元素個數。
- 樣例輸入:
-
2 2 0 0 0 0 4 4 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0
- 樣例輸出:
-
0 4
可以將上述問題轉化為求直方圖中最大的矩形的面積,將原矩陣中的每一行視為一個直方圖,對於每一行中的每一列的值為該行之上的1的個數,下面分別利用直方圖的算法來求解每一行中的最大值,然后求出全局最大值。代碼如下:
1 #include <iostream> 2 #include <stack> 3 #include <cstdio> 4 using namespace std; 5 6 int m, n; 7 int a[1000][1000]; 8 int b[2][1001]; 9 int f = 0; 10 11 int getMax() { 12 stack<int> s; 13 b[f][n] = 0; 14 int max = 0, tmp; 15 for (int i = 0; i <= n; ++i) { 16 if (s.empty() || b[f][s.top()] < b[f][i]) { 17 s.push(i); 18 } else { 19 int idx = s.top(); 20 s.pop(); 21 tmp = b[f][idx] * (s.empty() ? i : i - s.top() - 1); 22 max = (max > tmp) ? max : tmp; 23 --i; 24 } 25 } 26 return max; 27 } 28 29 void getRes() { 30 int max = getMax(), tmp; 31 ++f; f %= 2; 32 for (int i = 1; i < m; ++i) { 33 for (int j = 0; j < n; ++j) { 34 b[f][j] = (a[i][j] == 0) ? 0 : b[(f+1)%2][j] + 1; 35 } 36 tmp = getMax(); 37 ++f; f %= 2; 38 max = (max > tmp) ? max : tmp; 39 } 40 cout << max << endl; 41 } 42 43 int main() { 44 //freopen("1497.in", "r", stdin); 45 while (cin >> m >> n) { 46 f = 0; 47 for (int i = 0; i < m; ++i) { 48 for (int j = 0; j < n; ++j) { 49 cin >> a[i][j]; 50 if (i == 0) 51 b[0][j] = a[0][j]; 52 } 53 } 54 getRes(); 55 } 56 return 0; 57 } 58 59 /************************************************************** 60 Problem: 1497 61 User: hupo250 62 Language: C++ 63 Result: Accepted 64 Time:800 ms 65 Memory:5432 kb 66 ****************************************************************/