我正在尝试使用深度优先搜索算法来解决knight's tour问题。只要有两个选择导致死胡同,算法似乎就会循环。我知道这是因为每当找到死角时算法会再次将'wasVisited'布尔值重置为false,但我根本不知道如何修复它。
这是我到目前为止的代码:
public void dfs() {
vertexList[0].wasVisited = true;
theStack.push(0);
System.out.println("Visited: 0");
while (!theStack.isEmpty()) {
int v = getAdjUnvisitedVertex(theStack.peek());
if (v == -1) {
vertexList[lastVisited].wasVisited = false;
theStack.pop();
System.out.println("Go back to: " + theStack.peek());
} else {
vertexList[v].wasVisited = true;
lastVisited = v;
System.out.println("Visited: " + v);
theStack.push(v);
}
}
for (int j = 0; j < nVerts; j++) {
vertexList[j].wasVisited = false;
}
}
public int getAdjUnvisitedVertex(int v) {
for (int j = 0; j < nVerts; j++) {
if (adjMat[v][j] == 1 && vertexList[j].wasVisited == false) {
if (j != lastVisited) {
return j;
}
}
}
return -1;
}
提前致谢:)。
编辑:
这是更新的代码和输出:
public void dfs() {
vertexList[0].wasVisited = true;
theStack.push(0);
System.out.println("Visited: 0");
while (!theStack.isEmpty()) {
int v = getAdjUnvisitedVertex(theStack.peek());
if (v == -1) {
vertexList[lastVisited].wasVisited = false;
theStack.pop();
System.out.println("Go back to: " + theStack.peek());
int backTo = theStack.peek();
int newDestination = getNextAdjVertex(backTo, lastVisited);
lastVisited = newDestination;
while (newDestination == -1) {
theStack.pop();
backTo = theStack.peek();
System.out.println("Go back to: " + backTo);
newDestination = getNextAdjVertex(backTo, lastVisited);
lastVisited = newDestination;
if (newDestination != -1) {
vertexList[newDestination].wasVisited = false;
}
}
System.out.println("New Destination " + newDestination);
vertexList[newDestination].wasVisited = true;
lastVisited = newDestination;
System.out.println("Visited: " + newDestination);
theStack.push(newDestination);
} else {
vertexList[v].wasVisited = true;
lastVisited = v;
System.out.println("Visited: " + v);
theStack.push(v);
}
}
for (int j = 0; j < nVerts; j++) {
vertexList[j].wasVisited = false;
}
}
public int getNextAdjVertex(int currentVertex, int vertexICameFrom) {
for (int j = 0; j < nVerts; j++) {
if (adjMat[currentVertex][j] == 1 && vertexList[j].label != vertexICameFrom && vertexList[j].wasVisited == false) {
return j;
}
}
return -1;
}
public int getAdjUnvisitedVertex(int v) {
for (int j = 0; j < nVerts; j++) {
if (adjMat[v][j] == 1 && vertexList[j].wasVisited == false) {
if (j != lastVisited) {
return j;
}
}
}
return -1;
}
我正在尝试为5x5板解决此问题,因此有25个垂直(0 - 24)。这是当前问题变得更加明确的输出:
Visited: 0
Visited: 7
Visited: 4
Visited: 13
Visited: 2
Visited: 5
Visited: 12
Visited: 1
Visited: 8
Visited: 11
Visited: 18
Visited: 9
Go back to: 18
New Destination 21
Visited: 21
Visited: 10
Visited: 17
Visited: 6
Visited: 3
Visited: 14
Visited: 23
Visited: 16
Go back to: 23
Go back to: 14
Go back to: 3
Go back to: 6
New Destination 15
Visited: 15
Visited: 22
Visited: 19
Go back to: 22
Go back to: 15
Go back to: 6
Go back to: 17
New Destination 20
Visited: 20
Go back to: 17
New Destination 24
Visited: 24
Go back to: 17
New Destination 20
Visited: 20
Go back to: 17
New Destination 24
Visited: 24
当然,输出结束时的循环不应该发生。
答案 0 :(得分:4)
我将通过一个例子解释这个:
A - B - D
|
C
当代码到达节点C时,它找不到其他顶点要转到:v == -1
。然后会发生什么,它会清除C并返回B.这一切都很好。但是,在B我们只知道我们来自哪里(堆栈包含[A,B]
)。现在它找到了第一个未访问的顶点,但那又是C!
当你从C上升到B,然后找到要访问的下一个顶点时,你需要什么。您需要按顺序列出所有相邻的。
int getNextAdjVertex(int currentVertex,int vertexICameFrom) {
return the first vertex adjacent to currentVertex, bigger than vertexICameFrom
or -1 if it does not exist
}
if (v == -1) {
vertexList[lastVisited].wasVisited = false;
System.out.println("Go back to: " + theStack.peek());
//going down in the right direction:
int backTo = theStack.peek();
int newDestination = getNextAdjVertex(backTo,lastVisited);
//now same as the else part, a step downward
vertexList[newDestination].wasVisited = true;
lastVisited = newDestination;
System.out.println("Visited: " + newDestination);
theStack.push(newDestination);
}
只有一个小问题,如果newDestination == -1
你需要提高一个级别。你必须在一个循环中这样做,直到有一个未访问的顶点。
我认为问题出在getNextAdjVertex中。
System.out.println("Go back to: " + theStack.peek()+","+lastVisited);
将在发现问题时提供更多有用的信息。但我认为这应该有效:
public int getNextAdjVertex(int currentVertex, int vertexICameFrom) {
for (int j = vertexICameFrom+1; j < nVerts; j++) {
if (adjMat[currentVertex][j] == 1 && !vertexList[j].wasVisited) {
return j;
}
}
return -1;
}