我有一个已知的有限大小的瓷砖网格,可以形成地图。地图内的某些图块放置在称为“区域”的集合中。该区域是相连的,但对其形状一无所知。在大多数情况下,它是一个相当规则的斑点,但它可能在一个方向上被拉长,甚至可能有孔。我有兴趣找到该领土的(外)边界。
也就是说,我想要一个列表,列出所有与区域中的某个区域相关但未在区域中的区域。找到这个的有效方法是什么?
额外的困难是,我的图块是十六进制的,但是我怀疑这并没有太大的区别,每个图块仍标记有x和y整数坐标,并且给定一个图块,我可以轻松找到它的邻居。下面是一些示例:黑色是领土,蓝色是我要查找的边界。 这本身并不是一个难题,用伪python的一种简单算法是:
def find_border_of_territory(territory):
border = []
for tile in territory:
for neighbor in tile.neighbors():
if neighbor not in territory and neighbor not in border:
border.add(neighbor)
但是,这很慢,我想要更好的东西。我在整个领土上有一个O(n)循环,在所有邻居上有另一个循环(虽然很短,但仍然),然后我必须检查两个列表的成员资格,其中一个列表的大小为n。这给定了O(n ^ 2)的可怕比例。我可以通过使用集而不是边界和地区列表来将其简化为O(n),以便快速检查成员资格,但这仍然不是很好。我希望在很多情况下,由于面积和线比例缩放的原因,领土很大但边界很小。例如,如果区域是半径为5的十六进制,则其大小为91,而边框的大小仅为36。
谁能提出更好的建议?
编辑:
要回答以下一些问题。区域的大小范围从20到100左右不等。形成区域的图块集是一个对象的属性,而这个对象需要所有边界图块的集合。
最初,领土是作为一个街区创建的,然后大部分都是一块一块地获得。在这种情况下,确实最快的方法是保留一组边界并仅在获得的图块上更新它。有时,可能会对该地区进行重大更改-因此需要重新计算。
我现在认为,执行简单的边界查找算法是最好的解决方案。这带来的唯一额外复杂性是确保可能需要每次都重新计算边界,但不超过此数目。我非常有信心可以在当前框架中可靠地完成此操作。
至于时间,在我当前的代码中,我有一些例程需要检查该区域的每个图块。不是每回合,而是在创作时以及随后的创作中。即使它只是完整程序的很小一部分,也要花费我的测试代码运行时间的50%以上。因此,我渴望尽量减少重复。但是,测试代码涉及的对象创建要比程序正常运行(自然)要多得多,因此我意识到这可能不太相关。