我有这个迷宫,代表无向图。 这是它的样子:
ng-options="product as product.name for product in vm.filtered_products | filter : { isExtinguisher : vm.isExtinguisher, brand : vm.current_brand } : true"
在此图中,使用深度优先搜索,它显示了从起始节点到目标节点的解决方案。我作为起始节点的输入是11 3
2 3
0 3
1 4
5 4
5 7
6 7
7 8
8 9
9 10
6 11
7 11
,我的目标节点是0
。我作为目标路径获得的解决方案是1
,但如果再次分析,还有另一个解决方案0-3-11-7-5-4-1
。我的目的不是展示最佳解决方案,而是展示他们有多少解决方案,并在以后分析最佳解决方案。
我遇到的困难是我无法打印多个解决方案。它只打印0-3-11-6-7-5-4-1
没有其他内容,有时只打印0-3-11-7-5-4-1
因为我预计会有两个要打印。这是我到目前为止所做的代码:
0-3-11-6-7-5-4-1
MazeGraph源代码:
public class DepthFirstSearch {
private final boolean[] visited;
private final int sourceNode;
private final int[] pathTo;
/**
*
* @param mazeGraph
* @param sourceNode
* @param goal
*/
public DepthFirstSearch(MazeGraph mazeGraph, int sourceNode, int goal) {
this.sourceNode = sourceNode;
visited = new boolean[mazeGraph.node];
pathTo = new int[mazeGraph.node];
performRecursiveDFS(mazeGraph, sourceNode, goal);
}
//Perform recursive depth-first search
private void performRecursiveDFS(MazeGraph mazeGraph, int node, int goal) {
visited[node] = true;
for (int arc : mazeGraph.getAdjacencyList(node)) {
if (!visited[arc]) {
pathTo[arc] = node;
performRecursiveDFS(mazeGraph, arc, goal);
}
}
}
//Put path to goal in the stack
public Stack<Integer> pathTo(int toGoalNode) {
if (!visited[toGoalNode]) {
return null;
}
Stack<Integer> pathStack = new Stack<Integer>();
for (int pathToGoalNode = toGoalNode; pathToGoalNode != sourceNode; pathToGoalNode = pathTo[pathToGoalNode]) {
pathStack.push(pathToGoalNode);
}
pathStack.push(sourceNode);
reverseStack(pathStack);
return pathStack;
}
//Reverse the stack
public void reverseStack(Stack<Integer> stackToBeReverse) {
if (stackToBeReverse.isEmpty()) {
return;
}
int bottom = popBottomStack(stackToBeReverse);
reverseStack(stackToBeReverse);
stackToBeReverse.push(bottom);
}
//Pop the bottom of the stack
private int popBottomStack(Stack<Integer> stackToBeReverse) {
int popTopStack = stackToBeReverse.pop();
if (stackToBeReverse.isEmpty()) {
return popTopStack;
} else {
int bottomStack = popBottomStack(stackToBeReverse);
stackToBeReverse.push(popTopStack);
return bottomStack;
}
}
//Print the path to goal
public void printPath( int toGoal) {
if (visited[toGoal]) {
out.println("Path to Goal: ");
for (int x : pathTo(toGoal)) {
if (x == toGoal) {
out.print(x);
} else {
out.print(x + " - ");
}
}
out.println();
}
}
/**
*
* @param args
*/
public static void main(String[] args) {
Scanner scanFile = new Scanner(in);
out.print("Enter maze file: ");
String file = scanFile.nextLine();
out.print("Enter start node: ");
int startNode = scanFile.nextInt();
out.print("Enter goal node: ");
int goalNode = scanFile.nextInt();
MazeGraph mazeGraph = new MazeGraph(file);
mazeGraph.print();
out.println("Starting at 0\nGoal at 1");
DepthFirstSearch depthFirstSearch = new DepthFirstSearch(mazeGraph, startNode, goalNode);
depthFirstSearch.printPath( goalNode);
}
}
请向我解释为什么会发生这种情况并给我建议/建议如何改进这一点。检查我的代码质量是否正常,否则可以不检查。无论如何,先谢谢。
答案 0 :(得分:2)
您实际上很幸运,您的算法找到了一个路径,因为它有一个主要缺陷:如果您离开递归调用,则不会取消设置visited
。因此,您必须将此添加到performRecursiveDFS
:
private void performRecursiveDFS(MazeGraph mazeGraph, int node, int goal) {
visited[node] = true; //set visited
for (int arc : mazeGraph.getAdjacencyList(node)) {
if (!visited[arc]) {
pathTo[arc] = node;
performRecursiveDFS(mazeGraph, arc, goal);
}
}
visited[node] = false; //unset visited
}
这是必要的,因为你&#34; 回溯&#34;你正在寻找另一条道路,为此,你还没有去过node
。
此外,在递归调用中,您可以检查是否到达目标,如果是这种情况,请打印路径:
private void performRecursiveDFS(MazeGraph mazeGraph, int node, int goal) {
visited[node] = true; //set visited
if(node == goal) { //found the goal? Good, print it and backtrack.
printPath(goal);
} else {
for (int arc : mazeGraph.getAdjacencyList(node)) {
if (!visited[arc]) {
pathTo[arc] = node;
performRecursiveDFS(mazeGraph, arc, goal);
}
}
}
visited[node] = false; //unset visited
}
除了打印路径之外,您当然可以做其他事情,例如计数,将路径存储在列表中等等。
编辑:使用您提供的迷宫文件对其进行测试,我得到:
$ java DepthFirstSearch
Enter maze file: maze
Enter start node: 0
Enter goal node: 1
12 Nodes, 12 Arcs
0 connected to 3
1 connected to 4
2 connected to 3
3 connected to 11 2 0
4 connected to 1 5
5 connected to 4 7
6 connected to 7 11
7 connected to 5 6 8 11
8 connected to 7 9
9 connected to 8 10
10 connected to 9
11 connected to 3 6 7
Starting at 0
Goal at 1
Path to Goal:
0 - 3 - 11 - 6 - 7 - 5 - 4 - 1
Path to Goal:
0 - 3 - 11 - 7 - 5 - 4 - 1