-
问题引入:
Winter Camp2002,奶牛浴场
题意简述:
John要在矩形牛场中建造一个大型浴场,但是这个大型浴场不能包含任何一个奶牛的产奶点,但产奶点可以出在浴场的边界上。John的牛场和规划的浴场都是矩形,浴场要完全位于牛场之内,并且浴场的轮廓要与牛场的轮廓平行或者重合。要求所求浴场的面积尽可能大。
参数约定:产奶点的个数S不超过5000,牛场的范围N×M不超过30000×30000。
输入:
10 10 4 1 1 9 1 1 9 9 9
输出:
80
-
定义:
有效子矩形: 内部(不包含边界)没有障碍点的子矩形(四边均与坐标轴平行)
极大有效子矩形:不被任何一个有效子矩形包含(除本身)
最大有效子矩形:最大的有效子矩形
-
小性质 :
1. 极大有效子矩形的四条边无法向四边拓展, 也就是说四条边都存在障碍点或与大矩形边界重合
2.存在一个障碍点的矩形中最大有效子矩形一定是极大有效子矩形
-
【证明】:若最大有效子矩形不是极大有效子矩形,那么一定存在一个有效子矩形包括它,这与它的最大性相违背
-
解决问题:
1.思想一:枚举所有的极大有效子矩形
2.思想二:垂线法(后文介绍)
算法一 O(S2):
由思想一我们可以得知,我们要枚举极大有效子矩形,尽量不枚举无效的,不是极大的子矩形
而由性质一得知,极大子矩形边界中必含障碍点
所以我们将所有障碍点按横坐标排序, 枚举障碍点所在纵线(与y轴平行的线)为极大有效子矩形的左边界(关于左边界是矩形边界下文讨论),再从左到右的扫描障碍点,更新答案后再更新上下边界
-
更新答案:ans = max ( (上边界 - 下边界)* 横坐标之差 , ans)
-
边界初始化:up = 0, down = 矩形纵长
-
更新边界: 如果新点在左边界点的上方,up = min(up, 其纵坐标);否则 down = max(down, 其纵坐标);
-
bug & 改bug :
bug在于枚举过程中忽略了两类情况,一种是左边界在矩形左边界或右边界在矩形右边界的极大有效子矩形,另一种是左右边界都在矩形边界上(王知昆大佬的分类)。解决方法:将大矩形的四个顶点加入点集,然后横坐标排序跑一遍,纵坐标排序再跑一遍。横坐标跑的时候可以解决右边界问题,纵坐标跑时可以解决剩下问题(就像跑横坐标时可以解决上边界与下边界问题一样)
最后贴一下代码: