给出一个n*m的 矩阵 只含“0” 、“1”,
求出最大的一个全是1的子矩阵
一开始在想用什么奇淫技巧做。。。后来发现暴力做n次像POJ 2796的单调栈操作就好
预处理 h[i][j]为点【i】【j】处往上数连续的“1”的个数
那么对第i行做一次 得到的是 第i行为底边 高度为h[i][j] 的一个最大面积的矩形(面积为1的个数)
那么只要对每一行做一次,就得到整个矩阵的所有子矩阵中最大面积的一个子矩阵
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;
__int64 max (__int64 a,__int64 b)
{return a<b?b:a;}
struct node
{
__int64 l;
__int64 r;
__int64 h;
};
const int maxn=2005;
node tm[maxn];
__int64 top;
__int64 ans=-1;
void insert(node tt)
{
while(top&& tm[top].h>tt.h)
{
tm[top-1].r=tm[top].r;
tt.l=tm[top].l;
node t=tm[top];
ans=max(ans,(t.r-t.l+1)*t.h );
top--;
}
tm[++top]=tt;
}
int map[maxn][maxn];
int h[maxn][maxn];
int main()
{
__int64 n,m,j,i,x;
while(scanf("%I64d%I64d",&m,&n)!=EOF)
{
for (i=1;i<=m;i++)
{
for (j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
}
}
for (i=1;i<=n;i++)
{
int cun=0;
for (j=1;j<=m;j++)
{
if (map[j][i]==1)
cun++;
else
cun=0;
h[j][i]=cun; //该处往上有多少个连续“1”;
}
}
ans=-1;
node tt;
for (x=1;x<=m;x++)
{
top=0;
//对第x行 处理一次,得到该行为底边的最大矩形面积
for (i=1;i<=n;i++)
{
tt.h=h[x][i];
tt.l=tt.r=i;
insert(tt);
}
while(top)
{
tm[top-1].r=tm[top].r;
node t=tm[top];
ans=max(ans,(t.r-t.l+1)*t.h );
top--;
}
}
printf("%I64d\n",ans);
}
return 0;
}