首页 > 代码库 > [Jobdu] 题目1497:面积最大的全1子矩阵

[Jobdu] 题目1497:面积最大的全1子矩阵

题目描述:

在一个M * N的矩阵中,所有的元素只有0和1,从这个矩阵中找出一个面积最大的全1子矩阵,所谓最大是指元素1的个数最多。 

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行是两个整数m、n(1<=m、n<=1000):代表将要输入的矩阵的大小。
矩阵共有m行,每行有n个整数,分别是0或1,相邻两数之间严格用一个空格隔开。 

输出:

对应每个测试案例,输出矩阵中面积最大的全1子矩阵的元素个数。 

样例输入:
2 20 00 04 40 0 0 00 1 1 00 1 1 00 0 0 0
样例输出:
04

  可以将上述问题转化为求直方图中最大的矩形的面积,将原矩阵中的每一行视为一个直方图,对于每一行中的每一列的值为该行之上的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: 149761     User: hupo25062     Language: C++63     Result: Accepted64     Time:800 ms65     Memory:5432 kb66 ****************************************************************/