很经典的国家集训队论文:浅谈用极大化思想解决最大子矩形问题
最大子矩形问题:在一个给定的矩形网格中有一些障碍点,要找出网格内部不包含任何障碍点,且边界与坐标轴平行的最大子矩形。
悬线法 O(nm) O ( n m )
个人理解:枚举在子矩形底边上的一个点,将它尽可能地向上扩展成一条高线,然后将这条高左右尽可能地平移得到一个矩形,用此矩形更新答案。
枚举的复杂度已经达到了 O(nm) O ( n m ) ,所以我们需要预处理扩展和平移操作。
我们可以dp(或者叫递推也行)预处理:将每个点尽可能向上、向左、向右扩展到的位置存在数组 u[][],l[][],r[][] u [ ] [ ] , l [ ] [ ] , r [ ] [ ] 中(当然,存向上、向左、向右扩展的长度也行,但存位置对求答案来说更方便一点)
For i = 1 to n
For j = 1 to m
u[i][j] = (能从(i-1,j)走到(i,j)) ? u[i-1][j] : i;
l[i][j] = (能从(i,j-1)走到(i,j)) ? l[i][j-1] : j;
For j = m to 1
r[i][j] = (能从(i,j+1)走到(i,j)) ? r[i][j+1] : j;
预处理后我们得到了点 (i,j) ( i , j ) 的高线。但是对于向左和向右,我们需要知道的不是每个点向左向右扩展的位置,而是每条高线向左向右扩展的位置,这个问题我们可以递推出来:
For i = 2 to n
For j = 1 to m
if 能从(i-1,j)走到(i,j)
l[i][j] = max(l[i][j], l[i-1][j]
r[i][j] = min(r[i][j], r[i-1][j]
矩形面积就是 (r[i][j]−l[i][j]