Algorithm 矩阵遍历,规则必须命中某些单元格。采访

Algorithm 矩阵遍历,规则必须命中某些单元格。采访,algorithm,data-structures,graph,tree,traversal,Algorithm,Data Structures,Graph,Tree,Traversal,有一个矩阵包含白色单元格、黑色单元格和一个灰色单元格,如果Arra[N][N],则需要从(0,0)到(N-1,N-1) 限制条件: A.路径应仅覆盖白色单元格,并应通过灰色单元格。 B已访问的节点不能再次访问 白色单元格由0表示,黑色单元格由1表示,灰色单元格由2表示 根据我的研究,BFS不起作用。我不知道如何让DFS解决这个问题。有些人建议使用*搜索,但我不知道如何在这里部署它。有人建议首先找到到灰色单元的最短路径,然后从灰色单元找到到N-1,N-1的最短路径。但我相信这在某些情况下是行不通的

有一个矩阵包含白色单元格、黑色单元格和一个灰色单元格,如果Arra[N][N],则需要从(0,0)到(N-1,N-1) 限制条件: A.路径应仅覆盖白色单元格,并应通过灰色单元格。 B已访问的节点不能再次访问

白色单元格由0表示,黑色单元格由1表示,灰色单元格由2表示

根据我的研究,BFS不起作用。我不知道如何让DFS解决这个问题。有些人建议使用*搜索,但我不知道如何在这里部署它。有人建议首先找到到灰色单元的最短路径,然后从灰色单元找到到N-1,N-1的最短路径。但我相信这在某些情况下是行不通的,因为灰色单元格的最短路径会阻碍灰色单元格到目标单元格的路径。比如说,

-1 => start 
-2 => destination
0 => white space
1 => black space
2 => grey space

-1 0 0 0 0 
0  0 0 1 0 
0  1 0 2 0 
0  1 1 1 1 
0  0 0 0 -2
解决方法是采用较长的路径(从震源到正方形的右边缘,向下到2的行,然后到2)到灰色单元格,然后从那里到目的地


请用Java。

看起来像是最小成本最大流量的问题。将矩阵建模为一个图,在该图中,每个连接的单元之间的成本边为1,容量边为1,并在生成的图上运行最小成本最大流量算法


当然,由于每条边的成本为1,因此问题将简化为最大流量问题,可以通过以下方法解决。

a*有什么问题?这个想法很简单

作为初始列表,您只有白细胞。然后你让A找出从一开始到你的灰色细胞的路。一旦它找到了路径,你从灰色单元格一直到最后都要做同样的事情,但不仅要从你的列表中删除黑色单元格,还要删除那些你已经去过的地方

但是,我不会为您实现一个*。看一看,看一看


还注意到A*可能是过度的,因为所有的步骤都有相同的权重,最好考虑一个考虑到这一点的算法。

< P>对于像你这样的小问题,DFS应该足够好。从你现在的位置向四个方向走。如果你撞到墙、离开矩阵或重新访问单元格,请立即返回。离开牢房前,将其标记为已访问。(在返回之前,不要忘记清除该标志,以便其他分支可以使用该单元格。)

这将为您提供所有可能的路径,而不仅仅是最短的路径。当然,您必须跟踪路径,以便在到达目的地时可以对其进行处理。你还必须跟踪你是否通过灰色方块,只考虑到达目的地时的有效路径。

编辑:在伪代码中,算法如下所示:

traverse(curr, dest, path, pass):
    # curr: current cell
    # dest: destination cell
    # path: path, ie list of cells up to now
    # pass: have we passed the grey cell?

    # stop recursion short
    if curr is out of bounds: return
    if curr is impassable: return
    if curr is visited: return

    # treat cell as visited and add to path
    mark curr as visited
    path = path + [curr]
    if curr is grey: pass = true

    if curr is dest:
        if pass: add path to solution
    else:
        traverse(adj(curr, N), dest, path, pass)
        traverse(adj(curr, E), dest, path, pass)
        traverse(adj(curr, W), dest, path, pass)
        traverse(adj(curr, S), dest, path, pass)

    # clean up athis path for other recursions
    mark curr as not visited
    path = path[:-1]
您可以从以下内容开始搜索:

traverse(start, dest, [], false)
在显示“向解决方案添加路径”的位置,它取决于您想要什么。您可以只打印路径(可能会在出现异常时中止递归),您可以将其添加到全局解决方案列表中,您可以将另一个列表传递给函数并将其添加到此列表中。函数
adj(cell,dir)
返回相邻的单元格;这只是一种奇特的表达方式,类似于
(x,y+1)


您要求用Java提供解决方案,我对它不熟悉,所以我不能在这里给您任何实用的建议。单元坐标可能应该是元组,路径应该是单元向量,可以在集合中检查是否访问了单元。您比我更了解Java数据结构。

一些伪代码假设您有某种方法生成从一点到另一点的所有路径,以避免障碍:

for path1 in each path from start to grey:
  if exists path2 from grey to finish when path1 is no-go:
    return concatenation of path1 and path2
return nothing

在本例中,A*的错误在于,从起点到灰色单元格的最短路径阻止了仅使用未访问单元格到达目的地的所有可能性。当第一个A*没有给你一个有效的路径时,也许你可以用一个*从目的地开始。你是对的。您也可以使用*来查找从灰色单元格到目的地的路径。对不起,我指的是通过灰色单元格从目的地到起点的路径,当然,也就是说,交换起点和终点时也要这样做。(我不知道是否有死锁迷宫在两个方向上阻碍了通过灰色单元格的路径。)用这种方法是什么确保路径通过灰色单元格的?我想你的意思是,不是最小成本最大流量,但我在这一点上同意Peter。如果你从开始和结束都找到2的流量的最小成本(或者可能只是从指向两者的新顶点开始)对于灰色单元格,这应该是可行的。@Dukeling-谢谢你的评论,这对我理解这种方法有很大帮助。我认为使用灰色单元格作为接收器,开始/结束作为源是一个非常好的主意,+1我们如何为每个递归调用返回不同的路径并验证哪个路径是有效的?@Kelvin:你可以保留坐标在一个单独的向量中显示访问的单元格。或者,您可以在单元格中添加一个
next
字段,该字段对当前迭代中的路径有效。此外,您必须保留一个标志,说明您是否访问过灰色字段。当前路径和该标志属于递归状态。请注意s方法可以找到所有可能的路径,因为它不使用最短路径算法的优化。而且,对于具有广阔开放空间的迷宫,它的速度会很慢。但是,对于您的问题,该方法是可以的。如果我们将访问的节点标记为off,那么它将阻止其他递归尝试所有可能的路径,不是吗?如果我们将访问的节点标记为f、 然后它会阻止其他递归尝试所有的可能性,不是吗?如果我们做hashMap prev=hashMap();递归(prev,something);//1递归(prev,something 2);//2返回prev;并说recursion1和recursion2都向映射中添加了一个单元格,但我只希望节点是从recursion1得到的,而不是从recursion2得到的,我应该怎么做?比如说,如果按照您的建议找到了有效的解决方案,它应该如何递归地进行