Finding the longest path in a maze

Defining the Question

There’s not an obvious answer, because we need a set of criteria for choosing starting and ending points. Depending on the application, the following might all be requirements:

Perhaps the starting and ending points need to be at the edges of the maze (e.g., for printed mazes in children’s game books). Perhaps they need to be on opposite sides of the maze (e.g., for hedge mazes protecting a wizard’s castle). Or perhaps they can be anywhere at all (e.g., locations of staircases for a rogue-like game).

Are we looking to build a path with the longest total length? With the most turns? With the most choices?

I’ll answer the question as follows:

Suppose that an entrance and an exit can be placed anywhere. How can you find the entrance and exit points that lead to the longest path through the maze?

Turning the Maze Into a Graph

My representation for mazes in the previous installment wasn’t ideal for this task. I chose to consider a maze to be a list of walls: nice for drawing it, but less nice for deciding whether there’s a wall between two adjacent cells. So the first task will be to convert the list of walls into an adjacency list representation of a graph. For efficiency’s sake, I’ll go via a Set data structure, which I’ve imported qualified with the prefix ‘S’.

I also derived an Ord instance for Wall, so it can fit in the Set. The list comprehensions are a little unusual there, having no binding operations… but it certainly looks nicer than the alternative with if statements!

Doing the Search

Now we need a search algorithm to find the longest path in the graph. Note that the graph is a tree, which helps a lot, since we don’t need to worry about cycles, and any node can be chosen as a root. Depth first search works here, but the details are a bit tricky. The longest path in a subtree rooted at c is one of the following two things:

The longest subpath in one of its subtrees, or

The concatenation of the longest two paths from c to a leaf of two distinct subtrees.

At each step of the depth first search, we want to find two things: the longest paths to leaves in each of the subtrees, and the longest paths contained entirely within each of the subtrees. We can then consider all of the possibilities, and calculate the same two for the larger tree. The result looks like this:

3 Comments

The general term for what you are finding here is the Diameter of the graph (which is actually just the length, not the path itself). IE the maximum shortest path length. In general graphs it is not as efficient to find, but it is essentially the maximum value in the all-pairs shortest path matrix, so it can be computed in O(N^3) using Floyd-Warshall.