使用Haskell查找网格上两点之间的最短路径

时间:2010-03-15 23:09:25

标签: algorithm haskell shortest-path referential-transparency

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

但是在Haskell中解决这个问题给了我很大的麻烦。在涉及函数式编程时,我缺乏经验肯定是一个原因。

问题:

我将2D场分成相同大小的矩形。一个简单的网格。一些矩形是空的空间(并且可以通过)而其他矩形是无法通过的。给定起始矩形 A 和目标矩形 B ,我如何计算两者之间的最短路径?只能垂直和水平移动,步骤一个矩形大。

我如何在Haskell中完成此任务?代码片段肯定是受欢迎的,但肯定不是必要的。并且非常欢迎链接到更多资源!

谢谢!

2 个答案:

答案 0 :(得分:12)

我将网格表示为列表,列出[[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中找到有限地图。我假设在庞大的库中有一个堆(也就是优先级队列),但我不知道在哪里。

我希望这足以让你开始。

答案 1 :(得分:3)

嗯,您的类型将决定您的算法。

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

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