使用 DFS 优化解决 8-Puzzle
我正在使用 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 是已访问节点的哈希集。
堆栈空间不足。当我使用 -xss10m 将堆栈空间从 128k 增加到 10m 时,算法工作正常。不过我确信还可以进行大量其他优化。
任何提示将不胜感激。
I'm using Java to solve the 8-Puzzle problem using DFS.
this is what I came up with:
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) checks if move is possible. (if currentState.move(i) is out of bounds move() returns the same state)
i != lastMove makes sure that if in your last move you moved right you don't move left now (since it doesn't make sens)
visitedNodes is a HashSet of visited Nodes.
This is running out of stack space. When I use -xss10m to increase the stack space from 128k to 10m the algorithm works fine. However I'm sure there are a ton of other optimizations that can be made.
any tips would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,您可以创建一个堆栈而不是递归调用。
将lastMove 添加到EightPuzzle 类中。
这就是您得到的结果:
当您使用递归调用而不是迭代设计时,性能会显着下降。
之后,您可以使用 PriorityQueue 进一步优化(但它不会是真正的 DFS)。使用的启发式可以是曼哈顿距离。这样,第一个搜索的解就是最接近目标的解。它效率更高,但不是严格的DFS。
http://docs.oracle.com/javase /1.5.0/docs/api/java/util/PriorityQueue.html
First of all you can make a stack instead of a recursive call.
Add the lastMove to the EightPuzzle class.
This is what you get:
The performance drops significantly when you use recursive calls instead of an iterative design.
After that you can further optimize (but it will not be a true DFS) by using a PriorityQueue. The heuristic to use can be the Manhattan distance. This way the solution to be searched for the first is the closest to the target. It is more efficient but not strict DFS.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/PriorityQueue.html
我认为在继续递归调用之前标记已访问的状态可以大大加快搜索速度。除此之外,这个谜题没有太多的优化:你只需要尝试所有可能的动作。
I think you can speed up your search considerably by marking a state visited before proceeding with a recursive call. Other than that, there aren't too many optimizations for this puzzle: you simply need to try all possible moves.