1159 最大全0子矩阵

1159 最大全0子矩阵

/*
f(i,j)表示以(i,j)为右下角的最大全0子矩阵的边长
若a[i][j]==1,f(i,j)=0
否则:f(i,j)=min{ f(i-1,j),f(i,j-1),f(i-1,j-1) }+1
这样求得的是最大全0正方形子矩阵
要求长方形矩阵,上述思路行不通
假设以(i,j)为右下角的最大矩阵=12
它可能是3*4、4*3、2*6、6*2、1*12、12*1
按上述思路进行状态转移的话,取得最优值的方案不唯一时,
所有的方案需要都记下,用于后续的状态转移。

在长方形全0子矩阵中,考察某个位置(i,j)
在第i行中,包含(i,j)位置的全0区间长度>=长方形的宽
若第i行是子矩阵的最后一行,由(i,j)位置向上,连续0的个数>=长方形的高
设[l(i,j)..r(i,j)]是第i行上包含(i,j)的全0子区间
第i1行到第i2行且包含(i2,j)的子矩阵需满足的条件:
(i1..i2,j)均为0,i2-i1+1=矩阵的高
(i,j)对应的区间[l(i,j)..r(i,j)]>=矩阵的宽
孤立地计算l(i,j)、r(i,j),再枚举i1,i2,j,时间复杂度O(n^3)
l(i,j)与l(i,j-1),r(i,j)与r(i,j+1)之间有关系;
定义h(i,j)表示位置(i,j)向上连续0的个数,h(i,j)与h(i-1,j)之间有关系;
矩形的宽取决于[i1..i2]行中第j列上[l(i,j)..r(i,j)]的最小值
定义l(i,j),r(i,j)分别表示截止到第i行,之前的h(i,j)行中,全0元素的左右区间,
那么子矩阵的大小=(r(i,j)-l(i,j)+1)*h(i,j)
h(i,j)的递推关系
if(a[i][j]==0) h(i,j)=h(i,j)+1;

else h(i,j)=0;
l(i,j)的递推关系
定义mx表示之前0出现的左侧位置,初始值=1
if(a[i][j]==0){
l(i,j)=max(l(i-1,j),mx); //mx的值不变 
}else{ //a[i][j]===1,此时的h(i,j)=0,不存在包含(i,j)的子矩阵 
mx=j+1; l(i,j)=1; 
}
r(i,j)的递推关系
定义mn表示之前0出现的右侧位置,初始值=n
if(a[i][j]==0){
r(i,j)=min(mn,r(i-1,j))
}else{
mx=j-1; r(i,j)=n;
}
其中l(i,j),r(i,j),h(i,j)都可以压缩成一维数组。 
*/

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 const int maxn=2010;
 5 int n,a[maxn],l[maxn],r[maxn],h[maxn];
 6 int mx,mn,ans;
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for(int col=1;col<=n;col++)
11       l[col]=r[col]=col;
12     for(int row=1;row<=n;row++)
13     {
14         mx=1; mn=n;
15         for(int col=1;col<=n;col++)
16         {
17             scanf("%d",&a[col]);
18             if(a[col]==0)
19               h[col]=h[col]+1;
20             else
21               h[col]=0;
22             if(a[col]==1)
23               mx=col+1;
24             if(a[col]==0)
25               l[col]=max(l[col],mx);
26             else
27               l[col]=1;
28         }
29         for(int col=n;col>0;col--)
30         {
31             if(a[col]==1)
32               mn=col-1;
33             if(a[col]==0)
34               r[col]=min(r[col],mn);
35             else
36               r[col]=n;
37             ans=max(ans,h[col]*(r[col]-l[col]+1));
38         }
39     }
40     printf("%d\n",ans);
41     return 0;
42 }

 



posted @ 2016-04-09 10:46 Minepressure 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值