迷宫中最短的路径,有可能跳跃

时间:2014-02-26 21:09:56

标签: algorithm graph-algorithm maze

我有一个可以跳跃的迷宫:

0场 1壁 S-启动 E-端

A,B,C - 跳跃的可能性。当你输入带有这个字母的字段时,你会跳到其他具有相同字母的字段(在迷宫中只有两个这样的字段有一个字母(两个As,两个B,两个C)。

当你从A跳到第二个A时 - 你必须总是更进一步(你不能回到跳跃场,而不能移动到至少另一个场)。

示例迷宫:

1 1 E
A 1 0
S 1 A

从开始S到结束E的路径是(kartezian):( 0,0)(0,1)(2,0)(2,1)(2,2)

另一个例子:

A 0 B S
0 1 0 1
0 B 0 1
0 0 A E

输出应为(3,3)(2,3)(1,1)(0,1)(0,2)(0,3)(2,0)(3,0)

我使用BFS algorhitm它适用于正常的迷宫。但是无法想出如何正确添加跳跃可能性。我当前的伪代码(它适用于第一个示例,但在第二个示例中失败):

parents[points]; //array of parents
visited[points];    //array describing whether node was already visited

Que q;
q.put(startPoint);
while(!q.isEmpty)
{
     point = q.pop();
     if(CanJumpFromThisField(point))
     {
         jump = getJumpCoordinates(point);
         if(parents[point] != jump)
        continue;
     }
    for(allNeighbours(point)) //neighbour is field from left, righ, top, bottom 
    {
        if(neighbour.val != 1)
        {
        if(!CanJumpFromThisField(neighbour))
        {
            if(!visited(neighbour))
            {
                visited(neighbour) = true;
                parents(neighbour) = point;
                q.put(neighbour);
            }
        }
        else
        {
            jump = getJumpCoordinates(neighbour);
            if(!visited(jump))
            {
                parents(neighbour) = point;
                visited(neighbour)=true;
                parents(jump)=neighbour;
                visited(jump)=neighbour;
                q.put(jump);
            }
        }
    }
}
}

3 个答案:

答案 0 :(得分:0)

1)不要从startPoint S到EndPoint E进行BFS,而是从E进行BFS直到你访问所有点。

2)将最短路径的长度从每个点存储到E

3)要找到路径,从S遍历,选择路径长度最小的邻居,并保持遍历直至到达E.

注意:跳跃点也应视为邻居

复杂性:O(sizeof(网格))

答案 1 :(得分:0)

将邻居和邻居视为“目的地”。引入一种新方法,该方法枚举给定点的所有可能目的地(即邻居和跳转目的地)。

有效邻居是不是墙的邻居(即!= 1)。这将大大简化您的循环。

while(!q.isEmpty)
{
   point = q.pop();
   for(allDestinations(point)) //neighbours and jump destinations
   {
      if(!visited(neighbour))
      {
        visited(neighbour) = true;
        parents(neighbour) = point;
        q.put(neighbour);
      }
   }
}
allDestinations(point) returns list of points
{
  result = allDestinations(point).where (p=>p.Value != 1);
  if(CanJumpFromThisField(point))
  {
     jump = getJumpCoordinates(point);
     if (jump != point) 
       result.add(jump);
  }
}

同样,这是一些有趣的伪代码,但我认为你明白了。不要在一个方法或循环中加入太多逻辑。这让事情很难理解。

答案 2 :(得分:0)

BFS假设到达特定节点是相同的“成功”,尽管路径通向节点 - 这在您的问题中是不正确的。考虑你的4x4迷宫

 A 0 B S
 0 1 0 1
 0 B 0 1
 0 0 A E

当分析使B-B跳跃时,它从小区(1,1)向各个方向流动。它很快发现(2,0)并使A-A跳跃。然而,从A(0,3)向南的路径与从B(1,1)向西北方向的路径相遇,它们相互抵消。

问题在于使用迷宫的几何“相邻单元”关系作为BFS图中的过渡关系。在迷宫上面,单元格(2,1)和(1,0)都与(2,0)相邻,你可以制作步骤(1,0)(2,0)和( 2,0)(2,1)。但是,你不能去(1,0)(2,0)(2,1)路径,因为你输入(2,0)后就被迫跳转。

简单的解决方案是:对于每次跳转u-v,从迷宫中删除单元格uv(使其无法从相邻单元格中访问)以及每个x相邻uy相邻的每个v向图表添加x-y分支。

唉它只适用于没有相邻jupms的迷宫。例如这个修改

 A 0 B S
 0 1 0 1
 0 1 0 1
 0 B A E

使分析变得更加复杂。在这种情况下,您必须使用单向分支,例如仅允许x->uu->yy->vv->x转换。或者从广度优先切换到深度优先搜索...