9
悬线法求最大全0子矩阵
r,h,l都为滚动数组,l表示向左最远可以扩展的距离,r表示向右最远可以扩展的距离,h表示向上最远可以扩展的距离
具体思路参见浅谈有极大化思想解决最大子矩阵问题
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int m,n,i,j,r[2003],l[2003],h[2003],a[2003][2003],ans,la,ra;
int main()
{
scanf("%d",&n);
m=n;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for (i=1;i<=m;i++)
h[i]=0,l[i]=1,r[i]=m;
for (i=1;i<=n;i++)
{
la=0; ra=m+1;//la表示左边第一个障碍点的位置,ra表示右边第一个障碍点的位置
for (j=1;j<=m;j++)
if (a[i][j])//如果当前点为1,那么他就是一条悬线的起点
h[j]=0,la=j,l[j]=1;
else
h[j]++,l[j]=max(l[j],la+1);//h[j]++表示的是在上一行的基础上高度+1
for (j=m;j>0;j--)
if (a[i][j])
r[j]=m,ra=j;
else
r[j]=min(ra-1,r[j]),ans=max(ans,(r[j]-l[j]+1)*h[j]);
}
printf("%d",ans);
}