1.
True/False: The Knight’s Tour Graph contains as many vertices as there are tiles on a chessboard.
-
True
-
You are correct!
-
False
-
No; remember the implementation of Matrix graphs.
knightTour function takes four parameters: n, the current depth in the search tree; path, a list of vertices visited up to this point; u, the vertex in the graph we wish to explore; and limit the number of nodes in the path. The knightTour function is recursive. When the knightTour function is called, it first checks the base case condition. If we have a path that contains 64 vertices, we return from knightTour with a status of True, indicating that we have found a successful tour. If the path is not long enough we continue to explore one level deeper by choosing a new vertex to explore and calling knightTour recursively for that vertex.
knightTour with a status of False. In the breadth first search we used a queue to keep track of which vertex to visit next. Since depth first search is recursive, we are implicitly using a stack to help us with our backtracking. When we return from a call to knightTour with a status of False, in line 11, we remain inside the while loop and look at the next vertex in nbrList.
from pythonds.graphs import Graph, Vertex
def knightTour(n,path,u,limit):
u.setColor('gray')
path.append(u)
if n < limit:
nbrList = list(u.getConnections())
i = 0
done = False
while i < len(nbrList) and not done:
if nbrList[i].getColor() == 'white':
done = knightTour(n+1, path, nbrList[i], limit)
i = i + 1
if not done: # prepare to backtrack
path.pop()
u.setColor('white')
else:
done = True
return done
bool knightTour(int stepCount, int currentVertex,
vector<int>& path, vector<bool>& visited,
Graph& ktGraph, int n) {
visited[currentVertex] = true;
path.push_back(currentVertex);
if (stepCount == n * n) {
return true; // tour complete (recursive base case)
}
vector<int> nbrs = ktGraph.getVertex(currentVertex)->getConnections();
for (int nbr : nbrs) {
if (!visited[nbr]) {
if (knightTour(stepCount + 1, nbr, path, visited, ktGraph, n)) {
return true;
}
}
}
// backtrack
visited[currentVertex] = false;
path.pop_back();
return false;
}
vector<int> runKnightTour(int start, Graph& ktGraph, int n){
vector<int> path;
vector<bool> visited(n*n, false);
if (knightTour(1, start, path, visited, ktGraph, n)){
return path; //if there's a successful tour
}
return {};
}
knightTour in action. You can refer to the figures below to follow the steps of the search. For this example we will assume that the call to the getConnections method on line 6 orders the nodes in alphabetical order. We begin by calling knightTour(0,path,A,6).
knightTour starts with node A Figure 9.13.2. The nodes adjacent to A are B and D. Since B is before D alphabetically, DFS selects B to expand next as shown in Figure 9.13.3. Exploring B happens when knightTour is called recursively. B is adjacent to C and D, so knightTour elects to explore C next. However, as you can see in Figure 9.13.4 node C is a dead end with no adjacent white nodes. At this point we change the color of node C back to white. The call to knightTour returns a value of False. The return from the recursive call effectively backtracks the search to vertex B (see Figure 9.13.5). The next vertex on the list to explore is vertex D, so knightTour makes a recursive call moving to node D (see Figure 9.13.6). From vertex D on, knightTour can continue to make recursive calls until we get to node C again (see Figure 9.13.7, Figure 9.13.8, and Figure 9.13.9). However, this time when we get to node C the test n < limit fails so we know that we have exhausted all the nodes in the graph. At this point we can return True to indicate that we have made a successful tour of the graph. When we return the list, path has the values [A,B,D,E,F,C], which is the the order we need to traverse the graph to visit each node exactly once.








