Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 算法-在二维网格中查找最近的空正方形_Algorithm - Fatal编程技术网

Algorithm 算法-在二维网格中查找最近的空正方形

Algorithm 算法-在二维网格中查找最近的空正方形,algorithm,Algorithm,给定二维网格上的起始正方形(y,x),我想找到离它最近的空正方形。(注意:与起始正方形相邻的4个正方形应被视为比最近的4个对角线正方形更近。) 下图显示了在此网格上检查以下单元格所需的顺序: 网格是有边界的,但可以很大。实际上,起始坐标将随机位于网格周围。(因此,我不认为担心网格边界以外的坐标太重要了……) 我可以使用什么算法以这种方式在圆上迭代?一个简单的广度优先搜索就可以了。将要检查的每个邻居推到一堆上,按距离排序。您可能可以使用曼哈顿距离(dx+dy),但如果不使用平方径向距离(dx2+

给定二维网格上的起始正方形(y,x),我想找到离它最近的空正方形。(注意:与起始正方形相邻的4个正方形应被视为比最近的4个对角线正方形更近。)

下图显示了在此网格上检查以下单元格所需的顺序:

网格是有边界的,但可以很大。实际上,起始坐标将随机位于网格周围。(因此,我不认为担心网格边界以外的坐标太重要了……)


我可以使用什么算法以这种方式在圆上迭代?

一个简单的广度优先搜索就可以了。将要检查的每个邻居推到一堆上,按距离排序。您可能可以使用曼哈顿距离(dx+dy),但如果不使用平方径向距离(dx2+dy2)。每当你弹出一个项目,它将是最近的。如果是空的,你就找到了。否则,就把它的邻居推到堆上,然后继续弹出

我可能会使用正方形的径向距离,只添加相邻的正方形(不是对角线)。对角线将在稍后考虑,因为它们与其他正方形相邻。您确实需要一种方法来跟踪哪些方块已经被考虑过,这样您就不会再添加它们了。必须有一个聪明的动态规划方法来跟踪这一点,而不必每次搜索时清除大量布尔值。。。但是,如果这样说的话,一个大的布尔网格会做得很好。

它可以用BFS(广度优先搜索)来解决。我们必须对每个方块进行两次加工。第一次访问与当前正方形共享一条边的仍然未访问的正方形,下一次访问与当前正方形至少共享一个点的正方形(对角相邻的正方形)

我们可以使用两个不同的队列,以确保在第二次处理正方形之前,从源到当前正方形的距离相等的所有正方形至少已处理一次。:-)


平均运行时间:O(V*8)=>O(V)。其中V是网格内的正方形数

如果网格的内容经常更改,请使用前面答案中描述的方法,即首先搜索


如果网格的内容很少更改,并且曼哈顿距离适合您的应用程序,我的建议是计算二值化网格的距离(如果为空,则为0,否则为1)。距离变换对于曼哈顿距离非常简单,对于欧几里得距离更复杂)。此步骤的成本为2*N*M(网格元素数)。然后,对于每个请求,您可以以一种非常简单的方式访问邻居,即沿着从起始单元格开始的最小距离路径(如一些梯度下降),它将在最近的空单元格处停止。使用此算法搜索可能会更快,因为您不会以错误的方式查找超过1个单元格的空单元格。

第一次查看时,我想到了广度优先搜索(BFS)。我们可以使用-1或其他负值初始化距离数组,以跟踪未访问的正方形。这样,我们就不需要额外的网格来跟踪:)@falled当然,但您仍然需要在搜索之前清除网格。清除单独网格中存在的值会更快。它不必是负数,当为零时就可以了。例如,用搜索编号将跟踪保留在单独的网格中如何。是否在当前搜索中访问过此广场!这样我们就不需要清除它,因为它在访问该方块时总是会被更新:)假设
isvisted[][]
是保持跟踪的辅助网格,并且
isvisted[i][j]=2
当前我们正在处理搜索编号3,因此我们可以说在
O(1)
square(i,j)中没有被访问,可以在
O(1)中更新它
是的,这听起来更符合我建议的动态方法。只要您测试的搜索数小于当前搜索数。我建议使用小数据类型,如
unsigned short
,然后在当前搜索数返回到零时清除搜索网格(您必须跳过零并从一开始搜索)。不,您缺少一个关键点:您没有搜索整个网格,因此,您不能对“已访问”标志的内容进行假设。但是,如果您知道未访问的单元格的值始终小于当前搜索编号,则无需在每次搜索之前清除。将您的搜索编号取模2并使用布尔值将丢弃此重要信息。