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 }
时间: 2024-10-23 00:20:06

1159 最大全0子矩阵的相关文章

Codevs 1159 最大全0子矩阵 悬线法!!!!

1159 最大全0子矩阵 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多. 输入描述 Input Description 输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开. 输出描述 Output Description 输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数.

最大子段和||最大子矩阵和||最大全0子矩阵||最大全0子正方形

最大子段和(略) 定义一个最大值dp[i]表示以i结尾的最大子段和: 初始化: dp[0]=A[0]: dp[i]=max(dp[i-1]+A[i],A[i]) 即dp[i-1]+A[i]<0时 dp[i] = A[i]; 否则 dp[i]=dp[i-1]+A[i] 最大全0子矩阵 https://blog.csdn.net/Flere825/article/details/54605662 1159 最大全0子矩阵 /* #define N 2010 int a[N][N],ans,n; in

CODEVS1159 最大全0子矩阵

题目描述 Description 在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多. 思路:这个题最朴素的n^6的算法,超时美美的...然后想优化,从一个点向上方.左方.右方扩展,首先更新这个点向上能有多少个0h0,然后找左右h比h0大的作为左右边界,然后计算这个矩形的面积,最后输出最大值...这种构造的美丽算法,真心... 比较: 最大全0子正方形:f[i][j](以i,j为右下角的最大正方形的边长)=min(f[i-1][j],f[i][j-1],f[i-1][j-1])

[codevs1159]最大全0子矩阵(悬线法)

解题关键:悬线法模板题.注意此模板用到了滚动数组. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #define maxn 2002 using namespace std; typedef long long ll; int map[maxn][maxn],l[ma

最大全0/1子矩阵的探究

by MedalPluS [问题模型] 给定一个n*n的矩阵,求矩阵中面积最大的一个值全是0或1的子矩阵 [分析] (这里n*n完全可以改为n*m,但由于种种原因,等下代码里是n*n) 首先很容易想到一种解法,枚举这个子矩阵的左上方,和右下方,然后暴力统计,这样时间复杂度O(N6),这种做法很广泛 这肯定是不能满足我们的需求,那么应该怎么办呢?我们发现O(n2)的时间浪费在统计上,我们可以使用前缀和的手段,预处理 这样时间复杂度O(n4),还是很垃圾 在暴力种种优化都不行的时候,想一想贪心或者数

[BZOJ 1057][ZJOI 2007]棋盘制作(最大全0/1子矩阵)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1057 这题好像很早之前就看到过...那时候我还只会玩脚丫子,做这题完全像SB一样,记得那时我做了一会就放弃了. 如今看到这题感觉好做多了,此题预处理很巧妙,我们看一个棋盘,它的所有黑点的行标奇偶性都相同,列标的奇偶性也都相同.白点一样. 于是我们就可以预处理下,对于所有行标和列标奇偶性相同的点,保持它们的颜色不变,奇偶性不相同的点,反转它们的颜色,于是预处理后,我们要找的矩形在整

最大全0/1子矩阵

我们常常会遇到这样的问题:给定一个01矩阵,求其中全0/1的最大子矩阵的面积. 简单的模板题如:[Luogu]P4147,复杂点的有[Luogu]P5300 下面我们介绍一种比较容易的算法:悬线法 其实悬线法更多的是一种思想,许多最大化子矩阵的问题也能用这种思想解决. 我们想象有一条竖线,这条线的上端要么是边界,要么是障碍点,然后我们让这条线向左右拓展,直到碰到边界和障碍点. 求出一个位置的悬线后,我们就能直接计算$S = H(R - L + 1)$.然后对所有的$S$取$max$即为答案,正确

最大全1子矩阵

http://blog.csdn.net/zhang20072844/article/details/12925581 给出1个M*N的矩阵M1,里面的元素只有0或1,找出M1的一个子矩阵M2,M2中的元素只有1,并且M2的面积是最大的.输出M2的面积. Input 第1行:2个数m,n中间用空格分隔(2 <= m,n <= 100) 第2 - N + 1行:每行m个数,中间用空格分隔,均为0或1. Output 输出最大全是1的子矩阵的面积. Input 示例 3 3 1 1 0 1 1 1

Leetcode:Maximal Rectangle 最大全1子矩阵

Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area. 解题分析: 联想到 最大矩形面积 这一题,可以在O(n)时间内求出 最大的矩形面积 如果我们把每一行看成x坐标,那高度就是从那一行开始往上数的1的个数. 利用 最大矩形面积 的方法,在O(n2)时间内就可以求出每一行形成的“柱状