把表的每一行看作是一个直方图,求直方图内的最大长方形的问题。
使用栈来代替数组记录局部问题的解,栈中记录“仍有可能扩张的长方形的信息(记为rect)”,rect内含有两个信息,一个是长方形的高height,另一个是其左端的位置pos,首先将栈置为空,接下来对于直方图的各个值Hi(i=0,1,---,w-1),创建以Hi为高,以其下标i为位置的长方形rect,然后进行下列处理:
1.如果栈为空,将rect压入栈
2.如果栈顶长方形的高小于rect的高,将rect压入栈
3.如果栈顶长方形的高等于rect的高,不做处理
4.如果栈顶长方形的高大于rect的高。
只要栈不为空,且栈顶长方形的高大于等于rect的高,就从栈中取出长方形,同时计算面积并更新最大值,长方形的长等于“当前位置i”与之前记录的“左端位置pos”的差值
将rect压入栈,另外,这个rect的左端的位置pos为最后从栈中取出的长方形的pos值。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1400;
struct rectangle{
int height,pos;
};
int getmaxv(int size,int buffer[])
{
stack<rectangle>S;
int maxv=0;
buffer[size]=0;
for(int i=0;i<=size;i++){
rectangle rect;
rect.height=buffer[i];
rect.pos=i;
if(S.empty()){
S.push(rect);
}else{
if(S.top().height<rect.height){
S.push(rect);
}else if(S.top().height>rect.height){
int target=i;
while(!S.empty()&&S.top().height>=rect.height){
rectangle pre=S.top();
S.pop();
int area=pre.height*(i-pre.pos);
maxv=max(maxv,area);
target=pre.pos;
}
rect.pos=target;
S.push(rect);
}
}
}
return maxv;
}
int h,w;
int buffer[maxn][maxn];
int t[maxn][maxn];
int solve()
{
for(int j=0;j<w;j++){
for(int i=0;i<h;i++){
if(buffer[i][j]){
t[i][j]=0;
}else{
t[i][j]=(i>0)?t[i-1][j]+1:1;
}
}
}
// for(int i=0;i<h;i++){
// for(int j=0;j<w;j++){
// cout<<t[i][j]<<" ";
// }
// cout<<endl;
// }
int maxv=0;
for(int i=0;i<h;i++){
maxv=max(maxv,getmaxv(w,t[i]));
}
return maxv;
}
int main()
{
scanf("%d%d",&h,&w);
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
scanf("%d",&buffer[i][j]);
}
}
cout<<solve()<<endl;
return 0;
}