来自多色网格的最小矩形数量

时间:2018-01-21 01:17:39

标签: algorithm matrix xna

我已经在XNA roguelike游戏中工作了一段时间,我无法理解以下问题:开发一种算法将非二进制值矩阵划分为分组这些值的最小矩形。 / p>

示例:给出以下矩阵

  01234567
0 ---##*##
1 ---##*##
2 --------

算法应返回:

3x3 rectangle of '-'s starting at (0,0) 
2x2 rectangle of '#'s starting at (3, 0)
1x2 rectangle of '*'s starting at (5, 0)
2x2 rectangle of '#'s starting at (6, 0)
5x1 rectangle of '-'s starting at (3, 2)

为什么我这样做:我有一个相当大的地牢类型,大小约为500x500。如果我为每个瓷砖的Sprite单独调用“Draw”方法,我的FPS将太低。可以通过对类似纹理的图块进行分组并对它们应用纹理重复来优化此过程,这将显着减少GPU绘制调用的数量。例如,如果我的地图是前一个矩阵,而不是调用绘图16次,我只会调用它5次。

我看过一些算法可以在给定的二进制矩阵中给出最大的矩形矩形,但这不符合我的问题。

提前致谢!

2 个答案:

答案 0 :(得分:0)

一个可能的构建块是一个例程,给定两点,通过使用这些点作为对角形成的矩形是否都是相同的类型。我认为快速(但不可靠)的测试方法可以基于将每个类型映射到一个大的随机数,然后计算出一个以大模数为模的矩形内的数字之和。取矩形中的一个数字。如果矩形内的数字之和是矩形的大小乘以一个采样的数字,则假设矩形中的所有数字都相同。

在一个维度上,我们可以计算出所有累积和a,a + b,a + b + c,a + b + c + d,......在时间O(N)中然后,对于任何两个点,通过减去累积和来计算它们之间的间隔的总和:b + c + d = a + b + c + d - a。在二维中,我们可以使用累加和来计算每个点,来自具有x和y坐标的位置的所有数字的总和不大于该位置的(x,y)坐标。对于任何矩形,我们可以通过算出A-B-C + D计算出该矩形内的数字之和,其中A,B,C,D是二维累积和。

因此,通过预处理O(N),我们可以计算出一个表,该表允许我们计算在时间O(1)中由其对角指定的矩形内的数字之和。除非我们非常不走运,否则根据矩形的大小检查此总和乘以从矩形中提取的数字将告诉我们矩形是否都是相同的类型。

基于此,反复以未覆盖的随机点开始。只要在两个点之间的间隔属于同一类型,就向左移动一点并向左移动该点。只要两点形成的矩形属于同一类型,则向上移动该点。现在,只要由两个点形成的矩形具有相同的类型,就将第一个点向右和向下移动。现在你认为你有一个覆盖原点的大矩形。核实。万一它不是所有相同的类型,将该矩形添加到“被欺骗的”矩形列表中,您可以在将来检查并再次尝试。如果它是全部相同类型,则将其计为一个提取的矩形,并将其中的所有点标记为已覆盖。继续,直到覆盖所有点。

这是一个贪婪的算法,不会尝试产生最佳解决方案,但它应该相当快 - 最昂贵的部分是检查矩形是否真的是所有相同的类型,并且 - 假设你通过了测试 - 检查的每个单元也是一个覆盖的单元,因此整个过程的总成本应为O(N),其中N是输入数据的单元数。

答案 1 :(得分:0)

您可以使用广度优先搜索来分隔不同图块类型的每个区域。

在单个形状中挑选分区是NP难问题(请参阅https://en.wikipedia.org/wiki/Graph_partition),因此您无法找到保证最小矩形数的有效解决方案。但是,如果你不介意每个形状有一个或两个额外的矩形,并且你的形状相对较小,你可以提出将形状分割成接近最小值的矩形的算法。

我猜想可能有用的东西是选择一个具有最大连接图块的图块,然后使用递归算法从其中开始生长矩形以最大化尺寸。从形状中删除生成的矩形,然后重复,直到矩形中不再包含任何切片。同样,这将不会产生完美的结果,有些图表将返回超过最小数量的矩形,但它是一个易于实现的球场解决方案。通过更多努力,我相信您将能够找到更好的启发式方法并获得更好的结果。