浅谈 最大子矩阵

来源:互联网 发布:焊接模拟软件 编辑:程序博客网 时间:2024/06/06 04:03

例题:奶牛沐场

最大子矩阵面积,怎么求呢?

可以想到的是,这个矩阵一定是极大子矩阵。(什么?你不知道什么是极大子矩阵?百度吧。。。)

然后怎么求呢?

这个子矩阵每一条边都不可以伸展了,也就是说他的边界上一定有障碍点或者是与边界重合了。

算法一:

直接想到的是,上下左右枚举四个边界,再看看是不是满足条件。

复杂度?

O(n5)

原因是什么?我们枚举了很多没有用的矩阵。

很明显,我们不可以使用这个算法。

算法二

那么,我们可不可以优化一下?

我们只枚举左右边界,然后对范围内的点排序。每两个相邻的点加上左右边界就是目前的矩阵。

复杂度?

O(n3)

还是过不了啊。。。

原因何在?毕竟还是有很多的矩阵不是极大子矩阵

说了这么多,本质上都没有用到极大子矩阵这个性质。现在我们就要用用了。

想想怎么优化。

我们要保证以下几点:

  1. 所有枚举的矩阵都是有效的。

  2. 所有枚举的矩阵都是极大的。

算法三

首先我们把点从左到右标号。为了方便处理,我们把整个矩阵的四个角都变成障碍点。

然后把点从左到右排序。

第一次取1号点作为左边界,暂定整个矩阵的上下边界是目前上下边界。然后从左往右扫,遇到一个点,就修改上下边界。这样我们就得到所有的以1号点为左边界的极大有效子矩阵。

然后再是2号点,3号点……一直到(n−1)号点。

但是这样不完整。

为什么?还有右边界啊,你怎么保证右边界也这样呢?

所以按照同样的道理从右向左再来一次。

当然,如果左右边界不是排序后的第一个点的横坐标而是整个矩形的边界,那就需要特判了。

复杂度?

O(n2)

这就可以接受了。

但是,如过障碍点太密集,这个算法就不太优了。

算法四

考虑悬线法

什么是悬线?我们引进“有效竖线”。

有效竖线就是除了两个端点,不覆盖任何障碍点的竖线段。

于是,悬线就是上端点是一个障碍点或者是上端点是整个矩阵的边界的有效竖线。

这样的悬线有(n1)m个.
如果把一个极大子矩阵按照横坐标切成一条一条的,那么其中至少有一个悬线。

我们把一根悬线左右乱移动到尽可能最偏,这样左右边界就确定了。

还有上下边界

考虑点i与点i1

如果点i-1是障碍点,那么高度是1

如果不是,那么就是上一个高度+1。

这样就确定矩阵了。

复杂度?

O(nm)
也很清真啊,关键是不受到障碍点个数的影响。

当然,障碍点少的话,离散化一下也很好。