不小心瞄到题目提示,于是联想到之前做过的求最大子矩阵和的那道题。
这道题很类似,但是有些不同的是,可以计算的只有是0的矩阵,如果出现1就不能计算。
所以在求每个一维数组和的时候要保证序列中没有1。如果在原O(n^3)的算法上再判断就变成O(n^4)了。这里我用了空间换取时间的策略,另开一个三维数组me[i][j][k]记录第i行第j到k个元素之间是否包含1。
这样最后还是O(n^3)的算法。
在利用前缀和求一维数组和的时候,枚举起点终点,终点应该大于等于起点,结果写错了,WA了2次。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
bool a[105][105],me[105][105][105];
int s[105][105];
int main()
{
int M,N;
while(scanf("%d%d",&M,&N)&&!(!M&&!N))
{
int x;
memset(s,0,sizeof(s));
memset(a,0,sizeof(a));
memset(me,0,sizeof(me));
for(int i=1; i<=M; ++i)
for(int j=1; j<=N; ++j)
{
scanf("%d",&x);
if(x==0)
{
a[i][j]=false;
s[i][j]=s[i][j-1]+1;
}
else
{
a[i][j]=true;
s[i][j]=0;
}
}
for(int i=1; i<=M; ++i)
for(int j=1; j<=N; ++j)
{
bool ok=false;
for(int k=j; k<=N; ++k)
{
if(a[i][k]==true) ok=true;
me[i][j][k]=ok;
}
}
int mx=0;
for(int i=1; i<=N; ++i)
for(int j=i; j<=N; ++j)
{
int ans=0;
for(int k=1; k<=M; ++k)
{
if(me[k][i][j]==true)
{
ans=0;
continue;
}
int res=s[k][j]-s[k][i-1];
ans+=res;
mx=max(ans,mx);
}
}
printf("%d\n",mx);
}
return 0;
}