1、思路
- 用一个
height
数组来统计以当前行作为底的情况下,每个位置往上的1
的数量;
- 使用
单调栈
的方法遍历height
数组进栈,栈中存放height
数组元素的下标,目的是寻找数组中每个元素向左右两边最大能扩展的距离(即找到左右两边第一个比它小的数);
- 利用
单调栈
计算矩阵每一行所代表的height
数组,求出其中每个元素向左右两边扩展能达到的最大面积,取最大值。
2、代码
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int maxRecFromBottom(vector<int>& height)
{
if (height.empty()) return 0;
int maxArea = 0;
stack<int> stk;
//left与right分别代表左右方向上能够扩展的边界
for (int right = 0; right < height.size(); ++ right)
{
while (!stk.empty() && height[right] <= height[stk.top()])
{
int i = stk.top(); //要求的是以i位置的点左右扩展的面积,i的右边界为right
stk.pop();
int left = stk.empty() ? -1 : stk.top(); //i的左边界left为栈中下一个元素
int curArea = (right - left - 1) * height[i]; //计算i这个位置展开的面积
maxArea = max(maxArea, curArea);
}
stk.push(right);
}
while (!stk.empty())
{
int i = stk.top();
stk.pop();
int left = stk.empty() ? -1 : stk.top();
//右边已经没有比它小的值了,故右边界为数组的长度
int curArea = (height.size() - left - 1) * height[i];
maxArea = max(maxArea, curArea);
}
return maxArea;
}
int maxRecSize(vector<vector<int>>& map)
{
if (map.empty()) return 0;
int maxArea = 0;
vector<int> height(map[0].size());
for (int i = 0; i < map.size(); ++ i) //计算height数组
{
for (int j = 0; j < map[0].size(); ++ j)
{
height[j] = map[i][j] == 0 ? 0 : height[j] + 1;
}
maxArea = max(maxArea, maxRecFromBottom(height));
}
return maxArea;
}
int main()
{
int n, m;
cin >> n >> m;
vector<vector<int>> map(n, vector<int>(m));
for (int i = 0; i < n; ++ i)
{
for (int j = 0; j < m; ++ j)
{
cin >> map[i][j];
}
}
cout << maxRecSize(map) << endl;
return 0;
}