传送门
题目大意
给出一个N*M的矩阵,格子有黑白两种颜色,现在要找到黑白相间的、面积最大的矩形和正方形,输出它们的面积。
N,M <= 2000。
题解
对于在某个矩阵中求出满足要求的子矩阵,我们有一种常用方法——悬线法。
(其实我不知道为什么起这个名字 )
这种方法的主要思路是逐个处理,按列继承。对本题而言,我们的思路如下:
①逐个处理:用单调栈的方式,求出每一个点在满足要求的前提下,向左/右最多能延伸到哪一格:
for(rint i=1;i<=n;i++){
for(rint j=1;j<=m;j++){
b[i][j]=rad();
l[i][j]=r[i][j]=j;
up[i][j]=1;
}
}
for(rint i=1;i<=n;i++){
for(rint j=2;j<=m;j++){
if(b[i][j]!=b[i][j-1])
l[i][j]=l[i][j-1];
左边最远
}
}
for(rint i=1;i<=n;i++){
for(rint j=m-1;j>=1;j--){
if(b[i][j]!=b[i][j+1])
r[i][j]=r[i][j+1];
右边最远
}
}
②按列继承:再扫描一次矩阵,这一次我们除了考虑左右的限制,还要考虑上下的限制。为了方便处理,我们从上往下扫,求出每一格向上最多能延伸到多高。
for(rint i=1;i<=n;i++){
for(rint j=1;j<=n;j++){
if(i!=1&&b[i][j]!=b[i-1][j]){
l[i][j]=max(l[i][j],l[i-1][j]);
r[i][j]=min(r[i][j],r[i-1][j]);
up[i][j]+=up[i-1][j];
}
int a1=min(up[i][j],r[i][j]-l[i][j]+1);
ans1=max(ans1,up[i][j]*(r[i][j]-l[i][j]+1));/最大矩形
ans2=max(ans2,a1*a1);/最大正方形
}
}
注意,在这个过程中,我们会为了扩展高度而牺牲宽度,因此要每处理一格就更新一次答案。
然后这道题就圆满解决了~
一点点扩(jing)展(yan)
用悬线法解决最大子矩形的题貌似都很方便,比如 P4147 玉蟾宫和 P1387 最大正方形
(貌似就是本题1、2问拆开2333)
用类似的思路还可以解决 P1736 创意吃鱼法,本质上都是对从每个点统计扩展到对行和列的统计吧~


646

被折叠的 条评论
为什么被折叠?



