【问题标题】:Algorithm - Finding closest empty square a 2d grid算法 - 在二维网格中找到最近的空方格
【发布时间】:2013-07-18 21:52:24
【问题描述】:

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

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

网格是有界的,但可以很大。在实践中,起始坐标将随机位于网格周围。 (所以,我不认为担心网格边界之外的坐标太重要了......)

我可以使用什么算法以这种方式围绕圆进行迭代?

【问题讨论】:

  • 第一眼,我就想到了广度优先搜索 (BFS)

标签: algorithm


【解决方案1】:

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

我可能会使用正方形径向距离,只添加相邻的正方形(不是对角线)。稍后将考虑对角线,因为它们紧邻其他方格。您确实需要一种方法来跟踪已经考虑过哪些方格,这样您就不会再次添加它们。必须有一种巧妙的动态编程方法来跟踪这一点,而不必在每次搜索时都清除大量的布尔值……但话说回来,大量的布尔值就可以了。

【讨论】:

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

可以通过 BFS(广度优先搜索)来解决。我们必须处理每个正方形两次。第一次访问与当前方格共享边的未访问方格,下一次访问与当前方格至少共享一个点的方格(对角相邻方格)

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

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

【讨论】:

    【解决方案3】:

    如果网格的内容经常变化,请使用前面答案中描述的方法,即面包优先搜索。

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

    【讨论】:

      猜你喜欢
      • 2011-03-20
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-29
      相关资源
      最近更新 更多