九度 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;
}