滑动拼图的*启发式算法没有按预期工作

时间:2014-09-14 22:59:24

标签: java algorithm puzzle path-finding

我正在为滑动拼图实现解算器。在一个实现中,我使用了广度优先搜索。在第二个,我使用A *。但是,A *比BFS方法慢。我测量了BFS解决9x9拼图的平均时间约为.227秒,而A *则需要近2秒的时间。

我用于A *的启发式如下:F = G + H其中G是无序的块数,H是每个瓦片的曼哈顿距离与其在目标状态下的假定位置的总和(用户定义)。

以下是A *代码的相关部分(比较器用于优先级队列):

private void addToPriorityQueue(PuzzleState nextPS) {
    if (nextPS != null && !this.visited.contains(nextPS))
        pQueue.add(nextPS);
}

private boolean solveByAStar() {
    pQueue.clear();
    pQueue.add(this.initialState);

    while(!pQueue.isEmpty()) { 
        if (pQueue.size() > maxQueueSize)
            maxQueueSize = pQueue.size();

        this.currentState = pQueue.poll();

        if (this.currentState.equals(finalState)) { 
            return true;
        }

        visited.add(this.currentState);

        this.addToPriorityQueue(this.currentState.moveUp());
        this.addToPriorityQueue(this.currentState.moveDown());
        this.addToPriorityQueue(this.currentState.moveRight());
        this.addToPriorityQueue(this.currentState.moveLeft());

    }
    return false;
}

private class puzzleStateComparator implements Comparator<PuzzleState> {

    @Override
    public int compare(PuzzleState o1, PuzzleState o2) {
        //TODO

        int[] goalState = FastPuzzleSolver.this.initialState.getStateArray();

        int o1GScore = PuzzlePropertyUtility.numBlocksOutOfPlace(o1.getStateArray(), goalState);
        int o2GScore = PuzzlePropertyUtility.numBlocksOutOfPlace(o2.getStateArray(), goalState);

        int o1HScore = PuzzlePropertyUtility.calculateManhattanDistanceSum(o1.getStateArray(), goalState);
        int o2HScore = PuzzlePropertyUtility.calculateManhattanDistanceSum(o2.getStateArray(), goalState);



        return Integer.compare(o2GScore + o2HScore, o1GScore + o1HScore);


    }

}

以下是用于计算G和H的方法:

public static int numBlocksOutOfPlace(int[] ps, int[] goal) {
    int difference = 0;
    for (int i : ps) {
        if (ps[i] != goal[i])
                difference++;
    }
    return difference;
}

public static int calculateManhattanDistanceSum(int[] ps, int[] goal) {
    int rowSz = calculatePuzzleRowSize(ps);
    int manhattanDistanceSum = 0;
    for (int i = 0; i < ps.length; i++) {
        for (int j = 0; j < ps.length; j++) {
            if (ps[i] == goal[j])
                manhattanDistanceSum += (Math.abs(i/rowSz - j/rowSz) + Math.abs(i%rowSz - j%rowSz)); 
        }
    }
    return manhattanDistanceSum;
}

由于我的代码的效率还是因为我的启发式存在缺陷还是两者兼而有之,原因是否缓慢?

提前致谢。

0 个答案:

没有答案
相关问题