我如何在迷宫中获得最短的路线?

时间:2015-10-22 16:43:52

标签: r algorithm path-finding

我想在给迷宫作为矩阵的时候制作一个给出最短路径的代码。

http://plnkr.co/edit/kBSpRJLs6QA2D0jctKXB?p=preview

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

c(4,1,4,4,1,1)

并且,期望的结果是:count,其中1表示东,2表示北,3表示西,4表示南。

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

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

3 个答案:

答案 0 :(得分:8)

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

# 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

答案 1 :(得分:8)

我可能会使用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)

enter image description here

答案 2 :(得分:5)

一种可能性在于,在目标处设置值为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] 事实上无法访问,因此应将其排除在可能的起点之外。目的地不需要在拐角处。