单调栈/悬线法:2019银川区域赛K

传送门:https://nanti.jisuanke.com/t/42391

题目大意:给你两个 n * m 的二维排列(1 ~ n * m)。问你最大重合公共子矩阵。

题目思路:

这种问极大子矩阵的题目有两种方法求解:单调栈 / 悬线法

方法一:单调栈

1.关键:

求出每个点最远往上衍生多远的距离记为val.对于每一行,相当于求解以这一行为底边的最大柱状图面积。

2.思路:

对于每个点,正反跑一遍单调栈。求出往左最远能碰到的距离,往右最远能碰到的距离。(注意转移的时候左边界是如何衍生的,类似dp)

3.注意点:

这里需要注意连通性:单调栈中不仅每一列高度是递增的,而且要是在原矩阵中列也是两两相邻的。所以当新增一列时需判断连通性。若不连通,需要将栈清空再放入新的列.

方法二:悬线法(dp)  --  核心思想和 [方法一] 大同小异.

1.悬线:

对于每个点,他往上最多能走多少的线叫悬线。

2.原理:

极大矩阵的上边界一定被某个障碍物限制着(否则答案可以更大)。那么假设这个障碍物在第i列。那么第i列的极大矩阵的底边那个点到障碍物就是一条悬线.

3.1 答案求解

求解出每个点的1.悬线长,2.以该点为底,以悬线为高往左能够衍生多长,往右能衍生多长。答案面积就直接计算了。

①悬线长height数组:对于每个点(i,j),按(i - 1 , j)点转移即可。

②左右衍生长度left ,right数组:

第一遍:按(i - 1 , j)/(i , j - 1)点转移即可。

扫描二维码关注公众号,回复: 11881348 查看本文章

第二遍:对于那些height > 1 的点(i , j),它还需要考虑点(i - 1, j) 的  left 和 right 数组 对本行的限制。

3.2 过程要点

注意到:left,right数组再进行第一遍第二遍dp的时候概念是发生变化的

第一遍时:left,right数组单纯代表每个点往左/右边最多能衍生多少

第二遍时:left,right数组代表以该点悬线为高往左/右边最多能够衍生多少

所以一定要先让所有点左右衍生到尽头,再考虑上一行对本行的限制.(也就是按顺序来)

因为根据dp的含义: left数组只受左边第一个障碍物,还有上一层的left的影响。

如果left[i][j - 1] 提前算完两步了。它的含义也变了。那么在left[i][j]转移的时候left[i][j - 1]将不能转移。



知乎讲解:https://zhuanlan.zhihu.com/p/46382722

猜你喜欢

转载自blog.csdn.net/qq_35577488/article/details/108575668
今日推荐