题目描述 Description
在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多。
输入描述 Input Description
输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开。
输出描述 Output Description
输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数。
样例输入 Sample Input
5
0 1 0 1 0
0 0 0 0 0
0 0 0 0 1
1 0 0 0 0
0 1 0 0 0
样例输出 Sample Output
9
悬线法算法2模板题。可以加滚动数组来优化
【代码1】
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 2005
using namespace std;
int n,maxl,maxr,l[N][N],r[N][N],h[N][N],ans,a[N][N];
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
scanf("%d",&a[i][j]);
for (int i=1;i<=n;++i) r[0][i]=n;
for (int i=1;i<=n;++i){
maxl=1,maxr=n;
for (int j=1;j<=n;++j)
if (a[i][j]){
maxl=j+1;
h[i][j]=l[i][j]=0;
}
else{
h[i][j]=h[i-1][j]+1;
l[i][j]=max(maxl,l[i-1][j]);
}
for (int j=n;j>=1;--j)
if (a[i][j]){
maxr=j-1;
r[i][j]=n;
}
else{
r[i][j]=min(maxr,r[i-1][j]);
ans=max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);
}
}
printf("%d\n",ans);
}
【代码2】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 2005
int h[N],l[N],r[N],ans=0,a[N][N],maxl,maxr,n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++) r[i]=n;
for(int i=1;i<=n;i++){
maxl=1,maxr=n;
for(int j=1;j<=n;j++)
if(a[i][j]){
maxl=j+1;
h[j]=l[j]=0;
}
else{
h[j]++;
l[j]=max(l[j],maxl);
}
for(int j=n;j>=1;j--)
if(a[i][j]){
maxr=j-1;
r[j]=n;
}
else{
r[j]=min(r[j],maxr);
ans=max(ans,h[j]*(r[j]-l[j]+1));
}
}
printf("%d",ans);
}