Java 曼哈顿距离*

Java 曼哈顿距离*,java,artificial-intelligence,a-star,sliding-tile-puzzle,Java,Artificial Intelligence,A Star,Sliding Tile Puzzle,我正在使用*搜索算法实现一个NxN谜题解算器,并使用曼哈顿距离作为启发,我遇到了一个奇怪的错误(?),我无法理解 考虑这些难题(0元素为空白): (首字母) 102 754 863 (目标) 13 456 780 从初始状态到达解的最小移动次数为11。然而,我的解算器在17步中就达到了目标 这就是问题所在——我的解谜器主要以正确(最小)的移动次数解决可解的谜题,但对于这个特殊的谜题,我的解谜器超过了最小移动次数,我想我已经把问题归结为在这个特殊情况下对曼哈顿距离的错误计算 在这里,您可以看到我的

我正在使用*搜索算法实现一个NxN谜题解算器,并使用曼哈顿距离作为启发,我遇到了一个奇怪的错误(?),我无法理解

考虑这些难题(0元素为空白):
(首字母)

102

754

863

(目标)

13

456

780

从初始状态到达解的最小移动次数为11。然而,我的解算器在17步中就达到了目标

这就是问题所在——我的解谜器主要以正确(最小)的移动次数解决可解的谜题,但对于这个特殊的谜题,我的解谜器超过了最小移动次数,我想我已经把问题归结为在这个特殊情况下对曼哈顿距离的错误计算

在这里,您可以看到我的解算器正在做什么(在右边),以及一个经过测试的解算器正在做什么(Brian Borowski的优秀解算器,可用)

在第一步中,Brian的解算器立即选择将元素5向上推的解决方案,但我的解算器有其他想法,在stacktrace上(如图所示),我的解算器选择将元素2向左推的解决方案(由于该板的曼哈顿距离较低,该板位于优先队列的前面)。 我看不出问题出在哪里,我也不能责怪我的曼哈顿距离计算,因为它正确地解决了许多其他3x3难题

下面是我如何计算给定电路板的曼哈顿距离:

/**
 * Calculates sum of Manhattan distances for this board and stores it in private field to promote immutability.
 */
private void calculateManhattanDistance() {
    int manhattanDistanceSum = 0;
    for (int x = 0; x < N; x++) // x-dimension, traversing rows (i)
        for (int y = 0; y < N; y++) { // y-dimension, traversing cols (j)
            int value = tiles[x][y]; // tiles array contains board elements
            if (value != 0) { // we don't compute MD for element 0
                int targetX = (value - 1) / N; // expected x-coordinate (row)
                int targetY = (value - 1) % N; // expected y-coordinate (col)
                int dx = x - targetX; // x-distance to expected coordinate
                int dy = y - targetY; // y-distance to expected coordinate
                manhattanDistanceSum += Math.abs(dx) + Math.abs(dy); 
            } 
        }
    manhattanDistance = manhattanDistanceSum;
}
/**
*计算此板的曼哈顿距离之和,并将其存储在私有字段中,以提高不变性。
*/
私有void calculateManHatAndDistance(){
int曼哈顿锡=0;
对于(int x=0;x
如果您有任何见解或想法,我将不胜感激


如果需要任何额外的代码,我会立即发布。

如果您的启发式代码是可接受的(并且是,请检查),那么*始终返回最佳解决方案。可以较慢或较快(扩展更多或更少节点),但它会返回最佳解决方案

因此,由于启发式是可接受的,所以问题必须在*算法实现中


此外,它的第一步不同于最优步骤这一事实是毫无意义的:该算法可以正确地执行回溯,以在将来获得正确的解路径。所有打开的节点都是下一步的候选节点,而不仅仅是当前节点的子节点。

我在17步中解决这个问题的时候被卡在了同一个地方。问题是我只对A*算法使用启发式h(n),而选择下一个节点A*使用曼哈顿距离(启发式)+路径成本(从根到达节点的成本称为g(n)),以进行选择。 一旦你把它插入到算法中,它就像一个符咒


希望这能帮助那些身陷相同困境的人。

你确定这不会是a*实现中的错误,而不是距离启发吗?好吧,我已经想到了,但如果你检查stacktrace,我实际上认为一切都按预期进行。选择的解决方案是成本最低的解决方案,这就是我们想要的。pr问题是,我将次优的移动计算为最佳,并选择它作为路径。这让我怀疑距离计算,但我看不出错误。你是将你的跑步与Brian的解算器仅使用曼哈顿距离作为启发式进行比较?还是Brian的解算器也使用线性冲突(参见第二个参考资料).我觉得MD明智地将2作为第一步可能确实有道理,但这样的“贪婪”方法通常是次优的。A*只和你扔给它的启发式一样好。这是正确的-我只使用MD作为启发式。我已经设置了与我的解算器完全匹配的应用程序参数。你能看到给定MD计算中的任何错误吗。你对如何避免这种*“贪婪”有什么建议吗?为了测试你的A*你可以将启发式设置为0,它将像Dijkstra算法一样运行。Dijkstra保证返回最优解,除非有负权重。谢谢你的回答-我甚至可以说,虽然A*实现是正确的,但我似乎在计算一些既不是移动计数也不是pat计数的东西h访问次数。该算法实际上现在正确地解决了所有NxN难题,并且具有良好的时间安排,并正确地检测不可行的难题。我将很快更新我的原始帖子,并提供一些代码,以便我们能够发现困扰我几天的错误。对此,我非常感谢你!我已经被困在这个问题上一天多了就要放弃了