我目前正在接受我们的讲师在我们大学给我们的挑战。我们一直在研究最流行的寻路算法,如Dijkstra和A *。虽然,我认为这次挑战练习需要别的东西,而且让我感到难过。
需要解决的迷宫的直观表示:
色彩传奇
蓝色=起始节点
灰色=路径
绿色=目的地节点
它应该被解决的方式是,当移动完成时,必须完成它直到它与迷宫的边缘或障碍物(黑色边界)碰撞。它还需要以尽可能少的行移动来解决(在这种情况下为7)
我的问题:是否有人可以按照正确的方向推动我查看哪种算法?我认为Dijkstra / A *不是要走的路,考虑到最短的路径并不总是给出赋值的正确的路径。
答案 0 :(得分:1)
Dijkstra / A *仍然可以解决,需要改变的是邻居的配置。
一点背景,第一:
Dijkstra和A *是在图上制定的一般路径寻找算法。当我们在网格上移动一个角色而不是图形时,图形的位置可能不那么明显。但它仍然存在,构建图形的一种方法如下:
实际上,在涉及它们之间的一些配置和转换的大多数问题中,可以构造相应的图形,并应用Dijkstra / A *。因此,还可以解决诸如sliding puzzle,rubik's cube等问题,这些问题显然与在网格上移动的角色显着不同。但它们有状态,并且状态之间有转换,因此有可能尝试图搜索方法(这些方法,特别是像Dijkstra算法这样的不知情的方法,由于搜索空间很大,可能并不总是可行的,但是原则它可以应用它们。)
在您提到的问题中,图表与典型角色移动的图表没有太大区别:
正如Tamas Hegedus在评论部分所指出的那样,如果使用A *,应该选择启发函数是不明显的。
基于曼哈顿或欧几里德距离的标准启发法在这里无效,因为它们可能会高估与目标的距离。
一个有效的启发式方法是 id (row!= destination_row)+ id (col!= destination_col),其中 id 是身份函数, id (false)= 0且 id (true)= 1。
答案 1 :(得分:0)
Dijkstra / A *很好。您需要的是仔细考虑您认为图形节点和图形边缘的内容。
站在蓝色单元格(让我们称之为5,5
),你有三个有效的动作:
向右移动一个单元格(到6,5
)
向左移动四个单元格(到1,5
)
向上移动五个单元格(到5,1
)
请注意,您无法从5,5
转到4,5
或5,4
。将相同的推理应用于新节点(例如,从5,1
,您可以转到1,1
,10,1
和5,5
),您将获得运行Dijkstra /的图表A *。
答案 2 :(得分:0)
您需要评估每个可能的移动并采取最小距离的移动。如下所示:
int minDistance(int x, int y, int prevX, int prevY, int distance) {
if (CollionWithBorder(x, y) // can't take this path
return int.MAX_VALUE;
if (NoCollionWithBorder(x, y) // it's OK to take this path
{
// update the distance only when there is a long change in direction
if (LongDirectionChange(x, y, prevX, prevY))
distance = distance + 1;
)
if (ReachedDestination(x, y) // we're done
return distance;
// find the path with the minimum distance
return min(minDistance(x, y + 1, x, y, distance), // go right
minDistance(x + 1, y, x, y, distance), // go up
minDistance(x - 1, y, x, y, distance), // go down
minDistance(x, y - 1, x, y, distance)); // go left
}
bool LongDirectionChange(x, y, prevX, prevY) {
if (y-2 == prevY && x == prevX) ||(y == prevY && x-2 == prevX)
return true;
return false;
}
这是假设不允许对角线移动。如果是,请将它们添加到min()调用:
minDistance(x + 1, y + 1, distance), // go up diagonally to right
minDistance(x - 1, y - 1, distance), // go down diagonally to left
minDistance(x + 1, y - 1, distance), // go up diagonally to left
minDistance(x - 1, y + 1, distance), // go down diagonally to right