我需要解决以下问题: 我有一个网格,你可以在8个方向上移动,N,S,E,W,NE,NW,SE,SW。
正交移动成本总是1.如果前一次移动是正交的,或者前一次移动是对角线并且成本为2,则对角移动成本为1,否则成本为2。
以下几个例子可以更好地解释:
移动NE,NE将花费1 + 2 = 3
移动NE,E,NE将花费1 + 1 + 1 = 3
我认为这足以得到它的要点。
我不知道如何实现能够实现这一目标的A *算法。我的遗传功能:
private double heuresticDistance(Node p1, Node p2){
double dx = Math.abs(p1.x - p2.x);
double dy = Math.abs(p1.y - p2.y);
// D = 1d, D2 = 1.5d;
return D * (dx + dy) + (D2 - 2 * D) * Math.min(dx, dy);
}
显然在这种情况下并不好,并且在某些情况下它不会走最短的路径(成本方面),这意味着它可能采用不同的方式来降低成本。
如果不止一个,它总能找到最便宜的或最便宜的一个非常重要。
你可以给我一些提示吗?我的A *实现非常简单,我想我是根据wikipedia伪代码编写的。编辑:
public class Node{
public int x,y;
}
答案 0 :(得分:1)
您的启发式功能不是admissible。
查看从(0, 0)
到(1, 1)
的路径。您的启发式方法告诉您它等于1 * (1 + 1) + (1.5 - 2) * 1 = 1.5
。但路径是1
。所以你高估了你的目标,从而使你的启发式不允许,这导致A *找到错误的路径。
仔细看看A *,你会发现它需要可接受性(我也不记得一致性对你的情况是否重要)。
答案 1 :(得分:0)
参考维基百科文章A* search algorithm。你的启发式不是“单调的”,因为给定路径的成本取决于过去的选择。这是我的尝试。
任何路径都可以分为一系列orthagonal运动和一系列对角线运动。在启发式中,让我们移动对角线直到我们与目标成对角线。这确保了最大数量的额外成本。 NE-NE-E-E
另一方面,当我们均匀地混合orthagonal和对角线运动时,最好的情况发生:E-NE-E-NE。因此,对于每个orthagonal运动,我们可以将一个对角线运动视为orthagonal。
private double heuresticDistance(Node p1, Node p2, bool lastWasDiagonal) {
int dx = Math.abs(p1.x - p2.x);
int dy = Math.abs(p1.x - p2.x);
int diagonals = Math.min(dx, dy);
int orthagonals = Math.max(dx, dy) - diagonals;
// example: dx=3, dy=5. Move diagonally 3 times and orthagonally 2 times.
int temp = diagonals + orthagonals;
diagonals = Math.max(diagonals - orthagonals, 0);
orthagonals = temp - diagonals;
int lastDiagonalBonus = 0;
if( lastWasDiagonal && orthagonals < 1 )
lastDiagonalBonus = 1; // the special case that last move was diagonal and we have no orthagonal moves available to compensate
if( diagonals % 2 == 1 ) {
diagonals--; orthagonals++;
}
return diagonals * 3 / 2 + orthagonals * 1 + lastDiagonalBonus;
}