【问题标题】:Finding the shortest path between two points on a grid, using Haskell使用 Haskell 查找网格上两点之间的最短路径
【发布时间】:2011-01-27 21:50:18
【问题描述】:

这是一个我可以很容易地以非功能性方式解决的问题。

但是在 Haskell 中解决它给我带来了很大的问题。我在函数式编程方面缺乏经验肯定是一个原因。

问题:

我有一个 2D 字段,分为大小相等的矩形。一个简单的网格。一些矩形是空白的(可以通过),而另一些则无法通过。给定一个起始矩形 A 和一个目标矩形 B,我将如何计算两者之间的最短路径?只能垂直和水平移动,步长为一个大矩形。

我将如何在 Haskell 中完成这项工作?代码 sn-ps 肯定受欢迎,但也肯定不是必须的。也非常欢迎提供更多资源的链接!

谢谢!

【问题讨论】:

    标签: algorithm haskell shortest-path referential-transparency


    【解决方案1】:

    我会将网格表示为列表列表,输入[[Bool]]。我会定义一个函数来知道网格元素是否已满:

    type Grid = [[Bool]]
    isFullAt :: Grid -> (Int, Int) -> Bool  -- returns True for anything off-grid
    

    然后我会定义一个函数来查找邻居:

    neighbors :: (Int, Int) -> [(Int, Int)]
    

    要查找point 的非完整邻居,您可以使用filter (not . isFullAt) $ neighbors point 进行过滤。

    此时我要定义两个数据结构:

    • 将每个点映射到Maybe Cost
    • 将所有已知成本的点存储在一个堆中

    仅使用堆中的起始方A进行初始化,成本为零。

    然后循环如下:

    • 从堆中删除一个最小成本平方。
    • 如果它不在有限映射中,则将其及其成本添加到 c,并将所有未满的邻居添加到成本为 c+1 的堆中。

    当堆为空时,你将拥有所有可达点的成本,并且可以在有限映射中查找B。 (这个算法可能被称为“Dijkstra 算法”;我忘记了。)

    您可以在Data.Map 中找到有限映射。我假设在庞大的图书馆的某个地方有一个堆(又名优先级队列),但我不知道在哪里。

    我希望这足以让你开始。

    【讨论】:

    • 这听起来绝对是 Dijkstra 的算法,或者至少是它的一种变体。
    • 听起来像 A* 算法。 (我似乎无法正确发布维基百科链接)。
    【解决方案2】:

    好吧,你的类型将决定你的算法。

    您想使用什么数据类型来表示网格?二维数组?列表列表?一颗树?图表?

    如果您只想要有向图中的最短路径,最好使用 FGL(功能图包)中的内容。

    【讨论】:

      猜你喜欢
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      • 2018-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-03
      • 2012-12-18
      相关资源
      最近更新 更多