九度 1497 面积最大全1子矩阵
先预处理出每行连续1的个数,sum[i][j]表示第i行中到第j列为止的连续1的个数。
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j])
sum[i][j]=sum[i][j-1]+a[i][j];
else
sum[i][j]=0;
枚举i,j,并找出以sum[i][j]为宽的最大长度。
这样得到的便是以sum[i][j]为宽的最大子矩阵。
但这样的复杂度还是太高,我们需要一些辅助手段来优化。
再根据sum预处理列,ma[i][j]用来初步估算以sum[i][j]为宽的全1子矩阵的面积。每次求取时先用ans与ma[i][j]比较,ma[i][j]>ans说明以sum[i][j]为宽有可能得到面积更大的全1子矩阵,这样能够初步筛去一些明显得不到最大矩阵的情况,避免无谓操作。
void set_col(int c){//get ma[i][c]
for(int i=1;i<=n;i++){
if(!sum[i][c]) continue;
int ti=i;
int tsum=0;
while(sum[ti][c]){
tsum+=sum[ti][c];
ti++;
}
for(int j=i;j<ti;j++)
ma[j][c]=tsum;
i=ti;
}
}
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1005;
const LL Inf=1e18;
int a[maxn][maxn];
int sum[maxn][maxn];
int ma[maxn][maxn];
int n, m;
void set_col(int c){//get ma[i][c]
for(int i=1;i<=n;i++){
if(!sum[i][c]) continue;
int ti=i;
int tsum=0;
while(sum[ti][c]){
tsum+=sum[ti][c];
ti++;
}
for(int j=i;j<ti;j++)
ma[j][c]=tsum;
i=ti;
}
}
int main(){
int ans=0;
// freopen("matrix.in","r",stdin);//从in.txt中读取数据
// freopen("matrix.out","w",stdout);//输出到out.txt文件
while(~scanf("%d%d",&n, &m)){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j])
sum[i][j]=sum[i][j-1]+a[i][j];
else
sum[i][j]=0;
memset(ma,0,sizeof(ma));
for(int j=1;j<=m;j++){
set_col(j);
}
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(sum[i][j]&&ans<ma[i][j]){
int cnt=1;
for(int k=i-1;k>0;k--){
if(sum[i][j]>sum[k][j]) break;
cnt++;
}
for(int k=i+1;k<=n;k++){
if(sum[i][j]>sum[k][j]) break;
cnt++;
}
ans=max(ans,cnt*sum[i][j]);
}
printf("%d\n",ans);
}
return 0;
}