codevs 最大全0子矩阵

这个题可以预处理矩阵前缀和然后用n^3的方法解决,可是明显会超时,所以有一种n^2的算法。
我们可以一行一行的去算,设h[j]为从当前行开始向上数连续的0的个数(当前第i行也为0),如果当前位置等于1的话那么h[j]=0。
比如说样例:

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
那么每个位置的h[j]为
1 0 1 0 1
2 1 2 1 2
3 2 2 2 0
0 3 4 3 1
1 0 5 4 2
然后我们在求出来每一行h[j]的同时,去找当前位置可以到达的左边界和右边界。我们设l[j],r[j]为左右边界。我们设l[j],r[j]初始值都为j。显然,如果h[j]<=h[l[j]-1],那么l[j]=l[l[j]-1];对应着,如果h[j]<=h[r[j]+1],那么r[j]=r[r[j]+1];
我们来举个例子;
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
还有一个要注意的问题,因为到每一行的时候,h[j]都会跟着更新,所以我们每次求出来h[j]的时候应该紧跟着去求他的l和r,并且算面积。

#include<cstdio> 
#include<iostream>
#include<algorithm>
using namespace std;
int h[2100],map[2100][2100],l[2100],r[2100];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            cin>>map[i][j];
        }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){//一行一行处理,h[j]存储的是到第i行时,在第j列从i行开始往上的0的个数  
            if(map[i][j]==0)h[j]++;
            else h[j]=0;
        }
        for(int j=1;j<=n;j++){//每一行都要去算
            l[j]=j;
            while(l[j]>1&&h[j]<=h[l[j]-1])l[j]=l[l[j]-1];//如果能够扩展就向左扩展
        }
        for(int j=n;j>=1;j--){//注意这里要从右向左,因为我们是根据右边的更新左边的
            r[j]=j;
            while(r[j]<n&&h[j]<=h[r[j]+1])r[j]=r[r[j]+1];
        }
        for(int j=1;j<=n;j++)
            ans=max(h[j]*(r[j]-l[j]+1),ans);
    }
    cout<<ans<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值