【学习笔记】最大子矩形问题


问题类型

给定一个含有障碍点的矩形,找出内部不含障碍点的、边与整个矩形平行或重合的最大子矩形。


定义

有效子矩形:内部不含障碍点的、边与整个矩形平行或重合的最大子矩形。
极大子矩形:各边都与障碍点或整个矩形的边重合的有效子矩形。
最大子矩形:最大的有效子矩形。

最大子矩形 ⊆ \subseteq 极大子矩形 ⊆ \subseteq 有效子矩形


解决方案

采用 极大化思想

枚举所有极大子矩形,找到最大子矩形。

设矩形为 n × m n\times m n×m,障碍点数为 s s s

算法一

时间复杂度 O( s 2 s^2 s2 ),空间复杂度 O( s s s )

思路

首先考虑直接暴力枚举四个边界,然后判断是否为有效子矩形

时间复杂度 O( s 5 s^5 s5 ),产生大量的无效子矩形,妥妥的 TLE。

让我们对以上算法进行优化:

将所有障碍点按横坐标排序并编号为 1 , 2 , 3 , . . . 1,2,3,... 1,2,3,...
从左往右枚举极大子矩形左边界,以整个矩形上下边为边界。
向右扫描,枚举障碍点,修改上下边界使矩阵有效,复杂度 O( s 2 s^2 s2 )。

枚举左右边界时不要忘了加上整个矩形的左右边界!

特点

复杂度比较优秀,适用于障碍点较少的稀疏图

示题

Vijos 1055 WC2002 奶牛浴场

算法二(悬线法)

时间复杂度 O( n × m n\times m n×m ),空间复杂度 O( n × m n\times m n×m )

重点来了! \拍桌 \拍桌

定义

有效竖线:除了两个端点外,不覆盖任何一个障碍点的竖直线段。
悬线:上端覆盖了一个障碍点或者到达整个矩形上边界的有效竖线。

我们称以点 ( i , j ) (i,j) (i,j) 为底的悬线为点 ( i , j ) (i,j) (i,j) 对应的悬线

思路

一个矩形中共有 ( n − 1 ) × m (n-1)\times m (n1)×m 条悬线,即除了顶部的点外,其余的各点均有且只有一条与其对应的悬线。

枚举各条悬线,将其向左右两侧尽可能拓展,就可得到一个由 ( n − 1 ) × m (n-1)\times m (n1)×m 个悬线拓展形成的矩形的集合,而这个集合包含了所有的极大子矩形。

枚举悬线的时间复杂度是 O( n × m n\times m n×m ) 的,即我们要在 O( 1 1 1 ) 内拓展左右区间。

设 height [ i , j ] [ i,j ] [i,j] 为点 ( i , j ) (i,j) (i,j) 对应的悬线的长度,left [ i , j ] [i,j] [i,j] 为点 ( i , j ) (i,j) (i,j) 对应的悬线向左最多拓展到的位置,right [ i , j ] [i,j] [i,j] 为点 ( i , j ) (i,j) (i,j) 对应的悬线向右最多拓展到的位置。

left [ i , j ] [i,j] [i,j] 和 right [ i , j ] [i,j] [i,j]先初始化为点 ( i , j ) (i,j) (i,j) 向左右最多拓展到的位置。

这样,若 ( i − 1 , j ) (i-1,j) (i1,j) 为障碍点,height [ i , j ] [i,j] [i,j]=1,left [ i , j ] [i,j] [i,j]=0,right [ i , j ] [i,j] [i,j]= m m m

( i − 1 , j ) (i-1,j) (i1,j) 不为障碍点:

height [ i , j ] [i,j] [i,j]=height [ i − 1 , j ] + 1 [i-1,j]+1 [i1,j]+1
left [ i , j ] [i,j] [i,j]= m a x max max ( left [ i − 1 , j ] [i-1,j] [i1,j] , left [ i , j ] [i,j] [i,j] )
right [ i , j ] [i,j] [i,j]= m i n min min ( right [ i − 1 , j ] [i-1,j] [i1,j] , right [ i , j ] [i,j] [i,j] )

这样就可以利用递推式,在 O( 1 1 1 ) 的复杂度内拓展左右区间。

特点

复杂度与障碍点数无关,适合障碍点较稠密的矩阵求解,在障碍点较少时,不如算法一。

示题

洛谷 P1169 [ZJOI 2007]棋盘制作

题解将发至下一篇博客


参考资料

最大子矩阵问题&悬线法 学习笔记 Clove_unique

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值