- 题目描述:
-
在一个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 ****************************************************************/