Algorithm 在二维块栅格中查找矩形
假设我有一个由块组成的网格,7x12。我们使用颜色“*”、“%”、“@”和一个空单元格“-”Algorithm 在二维块栅格中查找矩形,algorithm,grid,Algorithm,Grid,假设我有一个由块组成的网格,7x12。我们使用颜色“*”、“%”、“@”和一个空单元格“-” 1 2 3 4 5 6 7 - - - - - - - 1 - - - - - - - 2 % % - - - - - 3 % % - - - - * 4 % % - - - @ % 5 @ @ @ - - @ % 6 @ @ * * * - * 7 * * * % % % % 8 % @ @ % * * % 9 % @ % % % % % 10 * * * % % @ @ 1
1 2 3 4 5 6 7
- - - - - - - 1
- - - - - - - 2
% % - - - - - 3
% % - - - - * 4
% % - - - @ % 5
@ @ @ - - @ % 6
@ @ * * * - * 7
* * * % % % % 8
% @ @ % * * % 9
% @ % % % % % 10
* * * % % @ @ 11
* * @ @ @ @ * 12
我想在这个网格中找到一个最小尺寸的矩形,我能找到的最大的,然后再更小,直到找不到大于或等于最小尺寸的矩形
在此示例中,考虑最小大小1x4、4x1、2x2,因此1x3无效,但2x3是无效的。如果我们想要最大的矩形,我们会发现:
- 4x1 at(4,8)
- (3,10)处的5x1
- 2x3 at(1,3)
- 2x2 at(6,1)
- 2x2 at(1,11)
- 4x1 at(3,12)
我在网上看到了很多关于矩形的问题,但是我很惊讶这个问题还没有被问到。我想的太难了,还是从来没有人想做这样的事情?注意:这是在假设您试图找到最大的
k
矩形的情况下运行的
我们知道,在最坏的情况下,我们必须至少查看网格中的每个节点一次。这意味着我们最好的情况下最差的演员阵容是O(len*wid)
您的蛮力将是O(len*len*wid*wid)
,使用“检查某一点上的矩形是O(len*wid)
,您可以多次这样做O(len*wid)
可能你发现情况并非如此,因为每次你找到一个矩形,你就有可能减少问题空间。我觉得“检查每个矩形”的蛮力方法将是最好的方法。不过,你可以做一些事情来加快速度
基本算法:
for(x = 1 .. wid) {
for(y = 1 .. len) {
Rectangle rect = biggestRectOriginatingAt(x,y);
// process this rectangle for being added
}
}
- 跟踪最大的
矩形。在进行过程中,您可以搜索符合条件的矩形的周长k
Rectangle biggestRectOriginatingAt(x,y) { area = areaOf(smallestEligibleRectangle); // if we want the biggest k rect's, this // returns the area of the kth biggest // known rectangle thus far for(i = 1 .. area) { tempwid = i templen = area / i tempx = x + tempwid tempy = y + templen checkForRectangle(x,y,tempx,tempy); // does x,y --> tempx,tempy form a rectangle? } }
- 另一个优化是使用绘画填充算法来查找最大的连续区域。这是
,这是一个很小的成本。这将允许您搜索最可能的区域,以查找要填充的大矩形O(len*wid)
请注意,这两种方法都没有减少最坏的情况。但是,它们确实减少了实际的预期运行时间。分别调用输入数组的宽度和高度W和H
我提到的最大矩形算法是为单色矩形设计的,但是如果你不能使它适应你的多色问题,你可以在开始第2步之前为每种颜色运行一次。我必须为我的第一人称射击手解决一个非常类似的问题。我在输入中使用它:
[[]
[]X][][]
[]X][X][X][X][X][X][X][X]
[][X][X][X][X][X][][][][] []X][X][X][X][]
[]X][X][X][X][]
[][X][[]
[[]
我在输出中得到:
[[]
[…]A[…]A[…]
[]B][G][G][G][F][E][E]
[][[G][G][G][F][][]]
[][D][G][G][G][G][D][b][b][b][b][b][b] [][D][G][G][G][G][D][b][b][b][b][b][b] [][C][]
[[]
这样更好。源代码(在GNU通用公共许可证版本2下)是,被大量评论。您可能需要根据自己的需要对其进行一些调整,就像j_random_hacker建议的那样。我自己的解决方案是
****|***|*** ************
****|***|*** ************
****#####*** ----#####---
****#####*** vs ****#####***
****#####*** ----#####---
****|***|*** ************