[EDIT: After seeing the other answer, I realise I answered the wrong question. Maybe this info is still useful? If not, I'll delete this. Let me know in a comment.]
They give a clear statement of what each entry of the DP table will hold. It's the solution to a particular subproblem consisting of just a particular subset of vertices, with the additional constraint that the path must end at a particular vertex:
Let dp[mask][i] be the length of the shortest Hamiltonian walk in the subgraph generated by vertices in mask, that ends in the vertex i.
Every path ends at some vertex, so the solution to the original problem (or at least its length) can be found by looking for the minimum of dp[(1 << n) - 1][i]
over all 0 <= i < n ((1 << n) - 1
is just a nice trick for creating a bitset with the bottommost n
bits all set to 1).
The main update rule (which I've slightly paraphrased below due to formatting limitations) could maybe benefit from more explanation:
dp[mask][i] = min(dp[mask XOR (1 << i)][j] + d(j, i)) over all j such that bit(j, mask) = 1 and (j, i) is an edge
So to populate dp[mask][i]
we want to solve the subproblem for the set of vertices in mask
, under the constraint that the last vertex in the path is i
. First, notice that any path P
that goes through all the vertices in mask
and ends at i
must have a final edge (assuming that there are at least 2 vertices in mask
). This edge will be from some non-i
vertex j
in mask
, to i
. For convenience, let k
be the number of vertices in mask
that have an out-edge to i
. Let Q
be the same path as P
, but with its final edge (j, i)
discarded: then the length of P
is length(Q) + d(j, i)
. Since any path can be decomposed this way, we could break up the set of all paths through mask
to i
into k
groups according to their final edge, find the best path in each group, and then pick the best of these k
minima, and this will guarantee that we haven't overlooked any possibilities.
More formally, to find the shortest path P
it would suffice to consider all k
possible final edges (j, i)
, for each such choice finding a path Q
through the remaining vertices in mask
(i.e., all vertices except for i
itself) that ends at j
and minimises length(Q) + d(j, i)
, and then picking the minimum of these minima.
At first, grouping by final edge doesn't seem to help much. But notice that for a particular choice of j
, any path Q
that ends at j
and minimises length(Q) + d(j, i)
also minimises length(Q)
and vice versa, since d(j, i)
is just a fixed extra cost when j
(and of course i
) are fixed. And it so happens that we already know such a path (or at least its length, which is all we actually need): it is dp[mask XOR (1 << i)][j]
! (1 << i)
means "the binary integer 1 shifted left i
times" -- this creates a bitset consisting of a single vertex, namely i
; the XOR
has the effect of removing this vertex from mask
(since we already know the corresponding bit must be 1 in mask
). All in all, mask XOR (1 << i)
means mask \ {i}
in more mathematical notation.
We still don't know which penultimate vertex j
is the best, so we have to try all k
of them and pick the best as before -- but finding the best path Q
for each choice of j
is now a simple O(1) array lookup instead of an exponential-time search :)