We are building an autonomous drone route planner that must visit N = 20 delivery drop points with minimum total travel distance.
Brute-force testing all permutations is (N - 1)!. For N = 20, $19! pprox 1.21 imes 10^{17}$, which would take hundreds of years of CPU time. The classic Held-Karp algorithm uses Bitmask Dynamic Programming to solve this in O(N^2 * 2^N). How does an integer bitmask represent subsets of cities, and how does the state transition work?
The Held-Karp Bitmask DP algorithm is the premier textbook demonstration of converting a factorial combinatorial explosion into a manageable exponential dynamic programming state space.
1. The Core Insight (Subproblem Overlap)
Suppose a drone visits cities in the order:
1 → 2 → 3 → 4.Another candidate path visits cities in the order:
1 → 3 → 2 → 4.Notice that in both cases, the set of visited cities is identical ({1, 2, 3, 4}), and the current ending city is identical (City 4)!
For future route choices (visiting the remaining cities 5 through 20), it does not matter how you traveled between 1, 2, and 3—all that matters is what is the minimum cost to have visited that exact subset and currently be sitting at City 4!
2. The State Definition
We define our DP state with two parameters:
dp(mask, u)mask: An integer whose binary bits represent the subset of visited cities. If bitiis1, Cityihas been visited. If bitiis0, Cityiis unvisited.u: The current city where the drone is currently parked.Transition:
To move to an unvisited city
v(where(mask & (1 << v)) == 0):Clean Python 3.12 Implementation with Memoization
Complexity Breakdown: From 10^17 down to 10^7
For $N = 20$:
Here is the iterative bottom-up C++20 Bitmask DP (Held-Karp) implementation for TSP.
Complexity: Runs in
O(N^2 * 2^N)time, solvingN=20in ~1 second.