HilbertMaze对Codility的任务

时间:2016-08-04 14:16:44

标签: algorithm hilbert-curve

任何人都可以给我一个关于如何从Codility处理以下任务的提示:https://codility.com/programmers/task/hilbert_maze/

我可以通过生成迷宫并使用BFS搜索最短路径来找到最短路径,但由于最坏情况下的时间复杂度预计为O(N)我不认为这会是正确的方法。 BFS的时间复杂度为O(| V | + | E])其中V是顶点数,E是边数。例如,如果N = 3,我们有一个大小为17x17的网格,直观显而易见的是我们只能在3个步骤中找到路径。

因此,指示的时间复杂度是错误的并且应该类似于M ^ 2,或者有一个快速的技巧来简单地计算两点之间的距离而不使用图算法。我找到了一些计算2个给定点的希尔伯特距离的算法(如果这是需要的),它使用位操作等但根本无法理解它们。此外,我认为该任务的目标是自己找出如何计算距离而不使用现有公式。

是否有人解决了这个任务并可以帮助我?谢谢!

1 个答案:

答案 0 :(得分:2)

以下是我提出的解决方案:

  1. 每个点位置都可以通过象限数组及其方向(它将具有N个元素)来定义 - 每个元素代表前一象限中的象限。整个迷宫具有向上的方向
  2. 您需要为这两个点定义此数组。例如:如果N = 2并且该点位于左下象限,那么它将具有左侧的方向。我们采用这个象限,我们旋转坐标系,使其方向相同。这样我们就可以在新系统中定义下一个象限和方向对。因此,如果我们在左下象限中有我们的点,那么它将具有左侧的方向,但由于这是相对于我们之前的方向(也是向左),这将成为向上的方向。
  3. 此时我们将所有象限和方向都缩小到包含我们观点的最小迷宫。从后面(从最小的迷宫)我们需要解决它们。每个迷宫都可以通过以下规则解决:

    • 如果我们当前象限中的点位于任何极值(意味着任何坐标的组件是象限的最低或最高),我们将它留在原来的位置,否则检查下一个点< / LI>
    • 如果我们的点是向下或在当前象限的中间,那么我们移动到象限最低中间点(这些相对于先前定义的方向,即:如果我们的方向向上,那么我们将移动我们的点在最顶端中点)
    • 如果我们的点向上(在相对方向上),我们将不得不将其移动到最顶端的中间点
  4. 存储这些移动,我们检查两个数组中是否有任何共同元素属于这两个点:

    • 如果不是,我们计算两个端点之间的距离,并且我们将两个移动列表中的所有距离相加(在此列表中,每个距离可以计算为坐标分量减法,即:abs(x1-x2)+ abs (Y1-Y2))
    • 如果我们有共同的元素,那么我们删除之后的所有移动,包括公共元素,我们计算之前提到的距离
  5. 这个解决方案可以进行优化,只是为了展示和想法开始。

    编辑:以下是我在Swift3中实现的上述解决方案:https://codility.com/demo/results/training9WWFXU-EWC/