【问题标题】:Solving 8-Puzzle using DFS optimizations使用 DFS 优化解决 8-Puzzle
【发布时间】:2012-02-09 01:26:52
【问题描述】:

我正在使用 Java 来解决使用 DFS 的 8-Puzzle 问题。

这是我想出的:

    public static boolean found = false;

        public void solveDepthFirst(EightPuzzle currentState, int lastMove){

            if(currentState.goal()){
                System.out.println(currentState);
                found = true;//to stop DFS when a solution is found (even if not optimal)
                return;
            }

            for(int i=0;i<numMoves;++i){
                if(found) return;

                EightPuzzle e = currentState.move(i);//0 = up, 1 = down, 2 = left, 3= right

                if(!e.equals(currentState) && i != lastMove
                        && !visitedNodes.contains(e.toString())){
                    solveDepthFirst(e, i);  
                }           
                     if(!visitedNodes.contains(currentState.toString())){
                visitedNodes.add(currentState.toString());
                     }
            }
        }

!e.equals(currentState) 检查是否可以移动。 (如果 currentState.move(i) 超出范围,则 move() 返回相同的状态)

i != lastMove 确保如果在上一次移动中你向右移动,你现在不会向左移动(因为它没有意义)

visitedNodes 是已访问节点的 HashSet。

堆栈空间不足。当我使用 -xss10m 将堆栈空间从 128k 增加到 10m 时,算法工作正常。但是,我确信可以进行大量其他优化。

任何提示将不胜感激。

【问题讨论】:

    标签: java artificial-intelligence stack-overflow depth-first-search


    【解决方案1】:

    首先,您可以创建堆栈而不是递归调用。 将 lastMove 添加到 EightPuzzle 类。

    这就是你得到的:

    // Queue<EightPuzzle> queue = new PriorityQueue<EightPuzzle>();
    Stack<EightPuzzle> stack = new Stack<EightPuzzle>();
    
    public void solveDepthFirst() {
    
        while (true) {
            EightPuzzle currentState = stack.pop(); // queue.poll();
            if (currentState.goal()) {
                System.out.println(currentState);
                found = true;// to stop DFS when a solution is found (even if
                                // not
                                // optimal)
                return;
            }
    
            for (int i = 0; i < 4; ++i) {
                if (found)
                    return;
    
                EightPuzzle e = currentState.move(i);// 0 = up, 1 = down, 2 =
                                                        // left,
                                                        // 3= right
    
                if (!e.equals(currentState) && i != currentState.getLastMove()
                        && !visitedNodes.contains(e)) {
                    stack.push(e); // queue.add(e);
                }
                if (!visitedNodes.contains(currentState.toString())) {
                    visitedNodes.add(currentState);
                }
            }
        }
    }
    

    当您使用递归调用而不是迭代设计时,性能会显着下降。

    之后,您可以使用 PriorityQueue 进一步优化(但它不会是真正的 DFS)。使用的启发式方法可以是曼哈顿距离。这样,首先要搜索的解决方案是最接近目标的。它更高效但不是严格的 DFS。

    http://docs.oracle.com/javase/1.5.0/docs/api/java/util/PriorityQueue.html

    【讨论】:

      【解决方案2】:

      我认为您可以通过在进行递归调用之前标记已访问的状态来大大加快搜索速度。除此之外,这个谜题没有太多优化:你只需要尝试所有可能的动作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-23
        • 2013-11-07
        • 1970-01-01
        • 2012-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多