Java 用A*算法识别最便宜路径

Java 用A*算法识别最便宜路径,java,algorithm,search,Java,Algorithm,Search,因此,我正在编写一个使用a*搜索算法的Java程序。该程序在二维数组上运行。它有一个出发点,一个目标和障碍。网格上的每个对象都是一个节点 SRRRRRRR RXXRRXXX RRRXXXRX RXRRXRRR XXXRRXRR RRRRRRRR XXRXRRXR XXXXRRRG S=开始,G=目标,R=有效移动平铺,X=非法移动平铺 我有两个ArrayList: -开放列表 -封闭列表 openList是一个从最便宜到最昂贵的可能移动列表。closedList是已访问且不会再次访问的节点列表

因此,我正在编写一个使用a*搜索算法的Java程序。该程序在二维数组上运行。它有一个出发点,一个目标和障碍。网格上的每个对象都是一个节点

SRRRRRRR
RXXRRXXX
RRRXXXRX
RXRRXRRR
XXXRRXRR
RRRRRRRR
XXRXRRXR
XXXXRRRG
S=开始,G=目标,R=有效移动平铺,X=非法移动平铺

我有两个ArrayList: -开放列表 -封闭列表

openList是一个从最便宜到最昂贵的可能移动列表。closedList是已访问且不会再次访问的节点列表。该算法将始终移动到openList中的第一个节点。然后,该节点将从openList中删除并添加到closedList的末尾

我的算法可以成功地从起点导航到目标。我遇到的问题是,我不确定如何从闭合节点列表中筛选出真正的路径。A*总是寻找最便宜的选择,这意味着它可能不会直接达到目标。openList根据移动成本对节点进行排序,因此即使算法距离目标只有一个节点,如果路径上有一个节点移动成本更低,那么它也会选择该节点。这意味着我可以保证找到最便宜的路径,但最后我的封闭列表将充满不在通往目标的最佳路径上的节点

最后,我的closedList给出了我的算法所采用的确切路径,而不是最便宜的路径


我的问题是:在我的算法将要研究的所有节点中,我如何区分最便宜路径上的节点和不在最便宜路径上的节点?

我强烈推荐,这将非常详细地介绍您可能想了解的关于寻路的所有信息


为了解决您的特定问题,您需要以某种方式存储访问节点时来自的节点,因此当您达到目标时,您只需沿着路径向后走。这可以通过
映射来完成,或者,您可以通过存储节点以外的内容来使用对父节点的引用:包含该节点的内容,以及在添加到列表时对访问该节点的节点的引用。

听起来您的成本函数可能被破坏了

在A*中,成本函数始终是迄今为止所通过路径的实际成本加上剩余距离的下限之和。有一些规则-与IIRC的规则相同

在这种情况下,用于下限剩余距离的明显启发式是

  • 剩余欧几里德距离-
    sqrt(xdist^2+ydist^2)
  • 曼哈顿剩余距离-
    xdist+ydist
  • 如果沿着间接路径走一步后的总成本估算值不大于直接走到目标后的总成本估算值,则唯一有效的方法是总成本估算值在两种方法中都相同。除非您在成本比较测试中添加一个平局断路器,否则A*将无法避免采取额外的步骤。但当直接路由可用时,它不会选择成本更高的路由——除非您的成本函数欺骗了它(或者您的代码有bug)

    在任何情况下,如果可能的移动直接指向目标,那么同样的成本无论如何都不应该发生在方形网格中

    您可能已经实现了Dijkstra而不是*。Dijstra的成本函数只是迄今为止行驶的总距离。没有人试图估计剩余的距离,因此也没有任何东西可以引导搜索朝着目标前进——它在各个方向上进行了平等的探索

    一种意外地以Dijkstra结束的方法是在剩余距离上使用明显的“未知”(但可接受)下限-零

    当然,在最后,你仍然有可能搜索到偏离最佳路径的节点——通常比你有一个好的a*启发式的节点要少,但即使这样,对于笨拙的地图也可能是错误的。请参阅-“您需要以某种方式存储访问节点时来自的节点”。对于您探索的每个节点,只有一个可能的最短距离可以到达-如果节点位于最短路径上,则该后退步骤是沿最短路径的反向步骤


    对于Dijkstra来说,你第一次探索一个地方总是为了找到最短的路。对于*而言,这不一定是真的IIRC(对于目标节点来说是真的,对于探索的其他节点来说不一定是真的),因此您可能需要存储到节点的最短距离以及后退步骤。

    很抱歉,我忘了提到移动有不同的成本。对角线移动成本为1,水平和垂直成本为2。@user2787386-好的,这意味着您的成本函数需要不太明显。对角线移动总是(远)小于水平和垂直步数以达到相同的位置,因此找到剩余距离有效下限的最简单方法是基于对角线步数。基本上,假设网格旋转45度,然后根据这些网格线计算曼哈顿/欧几里得距离。如果你也把它想象成一个有毕肖移动的棋盘,对角线只移动一半的节点。@user2787386-实际上,我认为你可以使用欧几里德距离或曼哈顿距离度量,只要单位剩余距离的单位成本。对于度量(但不是目前为止的距离),假设水平/垂直移动的成本为1。原因-在一个开放空间中水平(或垂直)移动两个单元格,成本最低的方法是采取两个对角移动-例如,向东北移动,然后向东南移动2*east。向东边的两个台阶收取一半的费用。这不是水平步的实际成本,但它是计算有效下限的一种简单方法。