思路
求最大子矩阵问题相当于对每一行求最大矩形问题问题,可以用单调栈处理。
因为子矩阵必有开始行和结束行,相当于枚举开始行,然后通过histogram的最大矩形问题保证到结束行为止都是1且最宽
代码
用自带的栈会超时(因为我用了结构体和scanf的关系)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
const int INF=0x3f3f3f3f;
const int maxn=2e3+50;
const int Mod=1000000007;
typedef long long ll;
using namespace std;
struct Node{
int h,startPos;
Node(){}
Node(int startPos,int h){
this->h=h;
this->startPos=startPos;
}
bool operator<(const Node &r)const{
return h<r.h;
}
};
int m,n;
Node st[maxn*10];
int solve(int h[]){
int ans=0;
int sz=0;
st[sz++]=Node(0,-1); //压入最低的,防止栈空 (这样就不用判断)
for(int i=1;i<=n+1;i++){
int height,curPos;
if (i>n) height=0; //全部处理完,将元素出栈(除了第一个)
else height=h[i];
curPos=i;
//一开始起始位置在当前位置
Node tmp=Node(curPos,height);
while(height<st[sz-1].h){
tmp=st[--sz];
int curAns=(curPos-tmp.startPos)*tmp.h;
ans=max(ans,curAns);
}
st[sz++]=Node(tmp.startPos,height);
}
return ans;
}
int s[maxn][maxn];
int cc[maxn][maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(~scanf("%d %d",&m,&n)){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++) {
scanf("%d",&s[i][j]);
}
}
for(int c=1;c<=n;c++){
int cnt=0;
for(int r=1;r<=m;r++){
if (s[r][c]) cc[r][c]=++cnt;
else cc[r][c]=cnt=0;
}
}
/*
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
printf("%d ",cc[i][j]);
}
puts("");
}*/
int ans=0;
for(int i=1;i<=m;i++) ans=max(ans,solve(cc[i]));
printf("%d\n",ans);
}
return 0;
}