假设一个布尔数组,如:
1111
1111
1110
1111
1001
现在你需要找到安排任何尺寸的最小矩形来实现这种形状的方法。所以,例如,你会发现:
+-++
| |+
| |
+-++
+ +
其中+是矩形的一角和|, - 矩形的边框。
我想做的是从最大可能的矩形开始,检查数组中是否有任何可以放置的位置,矩形覆盖的每个数组元素都是真的。如果存在这样的位置,矩形将被添加到列表中。之后我们检查数组的左侧空间是否有另一个点放入矩形,然后减小矩形的大小,并用剩余空间重复该过程,直到大小为0.
这应该会产生很好的效果,因为我们总是以大矩形开始,我们当然可以使用更少的矩形,这反过来意味着我们使用了少量的矩形。
但是,这只是我想到的一个概念,还没有付诸实践。这似乎效率很低,所以我想知道是否有任何已知的快速算法来实现这一目标?
答案 0 :(得分:3)
您是否考虑将二维数组视为像Karnaugh map?那样有一些算法(例如Quine-McClusky algorithm)用于合并布尔真值表的单元格,这类似于您正在尝试的要做。
答案 1 :(得分:3)
我真的陷入了对这个问题的思考,所以我研究了已发表的研究。事实证明,如果你想要一个最佳的解决方案,这是一个非常难以解决的问题(NP-Hard,如果你想要技术)。如果您不想接受我的话,请查看信息和控制中的“用于覆盖带有矩形的多边形的算法”。本文中有许多有趣的想法,作者给出了一种寻找最佳覆盖的算法。显然它不是在多项式时间内运行,但对于你的大小的问题实例来说它可能足够快。您甚至可能想先尝试一种更简单的耗尽技术,看看它是否适用于您感兴趣的问题。
这是我最初的建议,我不再保证是最佳的,尽管还没有提出反例:
从一个名为R的空矩形集合开始。对于数组中值为1的每个位置(i,j),找到包含(i,j)的最宽矩形W 1s,然后添加然后扩展W到最大高度的矩形M,它将包含所有1。如果不存在,则将M添加到集合R.完成后,对R进行传递并删除R中其他矩形完全覆盖的任何矩形。
答案 2 :(得分:1)
请注意,您描述的贪婪算法并不总是最佳的。考虑
01110 .XXX.
11111 XXXXX
01110 .XXX.
11111 XXXXX
01110 .XXX.
11111 XXXXX
01110 .XXX.
11111 XXXXX
01110 .XXX.
11111 XXXXX
01110 .XXX.
11111 XXXXX
01110 .XXX.
11111 XXXXX
如果你从最大的矩形开始,你得到高大的矩形,然后是很多小的边缘,产生15个矩形。另一方面,如果你只是做小的水平矩形,你可以只用14。
答案 3 :(得分:1)
存在O(N ^ 2)算法,允许您找到由1组成的最大矩形子矩阵。找到这个子矩阵并在其周围放置矩形。然后用零替换它内部的那些,以避免将它们包含在后续的矩形中。再次应用算法以查找下一个矩形。等等,直到没有人离开。
这种贪心算法当然不能保证最优解,在最坏的情况下其复杂度为O(N ^ 4)。
输入数据的最大大小是多少?