【问题标题】:How do I get the shortest route in a labyrinth?如何在迷宫中获得最短路线?
【发布时间】:2015-10-22 16:43:51
【问题描述】:

当给定一个迷宫作为矩阵时,我想编写一个给出最短路线的代码。

在这种情况下,这个迷宫的矩阵表示如下。

## [,1] [,2] [,3] [,4]
## [1,] 2 0 0 0
## [2,] 1 1 0 1
## [3,] 0 1 0 0
## [4,] 1 1 1 3
 , where  0 denotes inaccessible points, 1 denotes accessible points.
          2 denotes the starting point, and 3 denotes the destination.

并且,期望的结果是这样的:c(4,1,4,4,1,1),其中 1 表示东,2 表示北,3 表示西,4 表示南。

我猜一个可能的代码可能是一个函数,当它被给出迷宫的矩阵表示时,它给出了最短路径作为向量。

除了这种情况,我想知道是否可以将覆盖范围扩展到一般情况,尽管这似乎是多余的。 我想知道是否可以制作一个理想的代码,以便它覆盖任意 n x m 大小的矩阵,尽管只有 4 x 4 的情况就足够了。 而且我想知道起点和目的地是否可以位于顶点以外的任意点,尽管顶点情况就足够了。

【问题讨论】:

  • 我不确定这是一个编程问题——您需要先准备好搜索算法,然后再开始考虑如何编写代码。
  • 我不确定矩阵是否是代表这个问题的合适数据结构。有图表会更好。然后你有一个 ILP / QP 问题,你的目标是找到两个点之间的最短距离,每个顶点之间的距离相等。
  • 这不是一个正确答案的问题。有很多方法可以找到查找路径。查看:qiao.github.io/PathFinding.js/visual您需要决定哪种方法最适合您的数据。
  • 我认为您可能正在寻找 Dijkstra 算法的实现。虽然我从来没有见过这样的图表输出
  • @stasg 有大量算法标签,专门用于解决有关编程问题使用什么算法的问题。算法问题不一定是题外话。我也不明白这里对“太宽泛”的赞成票——这很可能用 igraph 用 5 行或更少的行来实现......

标签: r algorithm path-finding


【解决方案1】:

您可以构建一个图表来表示矩阵中位置之间的有效移动:

# Construct nodes and edges from matrix
(nodes <- which(m == 1 | m == 2 | m == 3, arr.ind=TRUE))
#       row col
#  [1,]   1   1
#  [2,]   2   1
#  [3,]   4   1
#  [4,]   2   2
#  [5,]   3   2
#  [6,]   4   2
#  [7,]   4   3
#  [8,]   2   4
#  [9,]   4   4
edges <- which(outer(seq_len(nrow(nodes)),seq_len(nrow(nodes)), function(x, y) abs(nodes[x,"row"] - nodes[y,"row"]) + abs(nodes[x,"col"] - nodes[y,"col"]) == 1), arr.ind=T)
(edges <- edges[edges[,"col"] > edges[,"row"],])
#      row col
# [1,]   1   2
# [2,]   2   4
# [3,]   4   5
# [4,]   3   6
# [5,]   5   6
# [6,]   6   7
# [7,]   7   9

library(igraph)
g <- graph.data.frame(edges, directed=FALSE, vertices=seq_len(nrow(nodes)))

那么你可以解决指定起点和终点位置之间的最短路径问题:

start.pos <- which(m == 2, arr.ind=TRUE)
start.node <- which(paste(nodes[,"row"], nodes[,"col"]) == paste(start.pos[,"row"], start.pos[,"col"]))
end.pos <- which(m == 3, arr.ind=TRUE)
end.node <- which(paste(nodes[,"row"], nodes[,"col"]) == paste(end.pos[,"row"], end.pos[,"col"]))
(sp <- nodes[get.shortest.paths(g, start.node, end.node)$vpath[[1]],])
#      row col
# [1,]   1   1
# [2,]   2   1
# [3,]   2   2
# [4,]   3   2
# [5,]   4   2
# [6,]   4   3
# [7,]   4   4

最后,您可以确定方向(1:东;2:北;3:西;4:南)作为对最终选定节点集的简单操作:

dx <- diff(sp[,"col"])
dy <- -diff(sp[,"row"])
(dirs <- ifelse(dx == 1, 1, ifelse(dy == 1, 2, ifelse(dx == -1, 3, 4))))
# [1] 4 1 4 4 1 1

此代码适用于任意大小的输入矩阵。

数据:

(m <- matrix(c(2, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 3), nrow=4))
#      [,1] [,2] [,3] [,4]
# [1,]    2    0    0    0
# [2,]    1    1    0    1
# [3,]    0    1    0    0
# [4,]    1    1    1    3

【讨论】:

  • 感谢您的友好回答。在您的建议中,我想问一下是否可以将代码操作为 "f=function(m){ .....}" 形式的代码,其中 m 是迷宫的给定矩阵因此,只要给出任意 4 x 4 大小的矩阵 m,函数 f 就会将结果作为向量给出。还有,我想问一下是否可以不使用任何包而使用代码,这样我就可以在没有任何包的帮助下完成一个自给自足的代码。
  • @kmee 您可以通过在我的所有代码之前添加f &lt;- function(m) { 和之后添加} 来获得您的功能。至于你的第二个问题,你当然可以在没有库的情况下实现最短路径算法(谷歌“Dijkstra 算法”),但我不会在这里这样做,因为它真的会重新实现轮子。请注意,如果您对可以使用或不能使用的软件包有要求,那么这些确实属于问题,不应作为事后的想法提及。
  • 感谢您的回答。我觉得在发布我的问题之前,我很难包含我必须考虑的所有因素,这可能是由于我的经验不足。我会记住的。而且我认为在发布问题之前我应该​​花一些时间,以免遗漏任何必不可少的条件。我是否可以再次发布有关此问题的附加条件的问题?谢谢。
  • @kmee 在这一点上你确实有一个新的编码问题——你想实现一个最短路径算法而不是使用库中的算法。请注意,仅要求其他人为您实现此功能可能是一个过于宽泛的问题,可能会被否决并关闭。最好自己尝试实现最短路径算法并在遇到问题时提出问题。
  • 好的,我自己试试。但我现在觉得R中的一切都非常晦涩难懂,几乎所有的例子我似乎都不知道该做什么,就像一个学生在大学第一次学习数学分析时感到苦恼一样。这只是幼稚的抱怨,所以忽略它。谢谢。
【解决方案2】:

我可能会使用 gdistance 包中的函数,在另一个设置 here 中演示:

library(gdistance) ## A package to "calculate distances and routes on geographic grids"

## Convert sample matrix to a spatial raster
m = matrix(c(2, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 3), nrow=4)
R <- raster(m)

## Convert start & end points to SpatialPoints objects
startPt <- SpatialPoints(xyFromCell(R, Which(R==2, cells=TRUE)))
endPt   <- SpatialPoints(xyFromCell(R, Which(R==3, cells=TRUE)))

## Find the shortest path between them
## (Note: gdistance requires that you 1st prepare a sparse "transition matrix"
##  whose values give the "conductance" of movement between pairs of cells)
tr1 <- transition(R, transitionFunction=mean, directions=4)
SPath <- shortestPath(tr1, startPt, endPt, output="SpatialLines")

## Extract your direction codes from the steps taken in getting from 
## one point to the other. 
## (Obfuscated, but it works. Use some other method if you prefer.)
steps <- sign(diff(coordinates(SPath)[[1]][[1]]))
(t(-steps)+c(2,3))[t(steps!=0)]
## [1] 4 1 4 4 1 1

## Graphical check that this works
plot(R>0)
plot(rBind(startPt, endPt), col=c("yellow", "orange"), pch=16, cex=2, add=TRUE)
plot(SPath, col="red", lwd=2, add=TRUE)

【讨论】:

    【解决方案3】:

    一种可能性是在目标处设置一个值为 1 的矩阵,并以每个正方形的 0.9 的速率减小该值,作为距目的地的曼哈顿距离的函数。障碍物的值为零,起点是任意的。

    一旦定义了这样的矩阵,通过迭代到值增加最大的相邻方格来获得最短路径。

    例如,在 M. Sugiyama 的“统计强化学习”一书的第一章中描述了这种方法。

    所以你的矩阵可能看起来像这样:

         [,1]  [,2]  [,3] [,4]
    [1,] 0.53  0.00  0.0  0.00
    [2,] 0.59  0.66  0.0  0.81
    [3,] 0.00  0.73  0.0  0.00
    [4,] 0.73  0.81  0.9  1.00
    

    算法是:

    • 选择一个非零值的起始方块
    • 移动到距离您一步之遥的方格中价值最高的方格。
    • 重复上一步,直到到达值为 1 的正方形

    请注意,[2,4] 的值事实上不可访问,因此应将其排除为可能的起点。目的地不必在拐角处。

    【讨论】:

    • 算法的第 2 步是“移动到距离您一步之遥的方格中值最高的方格。”如何在具有相同值的相邻单元格之间进行选择?
    • @RobertH 在这种情况下不需要选择,可以选择任意一个,只要它是最高值。如果两个单元格具有相同的值,则生成的路径将具有相同的长度(例如,先向左然后向上,而不是先向上然后向左)。
    猜你喜欢
    • 2018-03-24
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多