Worked examples — Bitmask DP — TSP intro
This is the practice-until-it-hurts companion to the parent TSP intro. There we built the state dp[SET][SPOT] and the transition. Here we run it across every case the problem can throw at you — tiny inputs, degenerate graphs, asymmetric costs, path-vs-cycle, and an exam trap. If a scenario surprises you in an exam, it should be because you forgot it, not because you never saw it.
The scenario matrix
Every cell below is a distinct way the DP can behave. Each worked example is tagged with the cell(s) it covers.
| Cell | Case class | What's special | Covered by |
|---|---|---|---|
| A | Smallest non-trivial () | Two cities, one round trip — the base case barely moves | Ex 1 |
| B | Symmetric triangle () | Both directions equal; ties everywhere | Ex 2 |
| C | Asymmetric graph | dist[i][j] ≠ dist[j][i] (one-way roads) — direction matters |
Ex 3 |
| D | Missing edge (∞ cost) | No road between two cities; DP must route around | Ex 4 |
| E | Degenerate: unreachable state | A dp[mask][i] that stays and must be skipped |
Ex 4, Ex 6 |
| F | Path, not cycle | Drop the return edge; answer changes | Ex 5 |
| G | Real-world word problem | Translate a story into a dist matrix |
Ex 6 |
| H | Exam twist: "fixed start ≠ fixed end" | Start at 0, must end at a given city | Ex 7 |
| I | Limiting behaviour / sanity | What the numbers become as grows; brute-force cross-check | Ex 8 |
Example 1 — Cell A: the smallest tour ()
Steps.
- Base:
dp[01][0] = dp[1][0] = 0. Why this step? Every DP starts by seeding the only state we know for free: sitting at the start, having visited only , cost . - Reach city 1:
dp[11][1] = dp[01][0] + dist[0][1] = 0 + 7 = 7. Why this step?mask=11means visited; to end at 1 we peel the last edge . - Close the tour:
full = 11, answer . Why this step? TSP is a cycle, so we must pay the return edge (Mistake #3 in the parent).
Verify: the only possible route is . There is nothing to minimise over — matches. ✓ (Units: cost units, consistent.)
Example 2 — Cell B: symmetric triangle, ties ()
This is the parent's Worked Example 1, re-run so the figure below shows both competing final routes side by side.

Steps.
dp[011][1] = 0 + 10 = 10(go );dp[101][2] = 0 + 15 = 15(go ). Why this step? From the base state we branch to each unvisited city — these are the two first moves.dp[111][2] = dp[011][1] + \text{dist}[1][2] = 10 + 20 = 30. Why this step? Fill the mask ending at 2, arriving from 1.dp[111][1] = dp[101][2] + \text{dist}[2][1] = 15 + 20 = 35. Why this step? The other way to fill everything, ending at 1, arriving from 2.- Close: . Why this step? Two full-mask states, two return edges — take the cheaper.
Verify: ; . The tie is real (look at the two coloured loops in the figure — same edges, opposite direction). ✓
Example 3 — Cell C: asymmetric graph (one-way roads)
Steps.
- First moves:
dp[011][1] = dist[0][1] = 1;dp[101][2] = dist[0][2] = 9. Why this step? Direction now matters — costs 1 but costs 9. The DP records both honestly. dp[111][2] = dp[011][1] + dist[1][2] = 1 + 2 = 3.dp[111][1] = dp[101][2] + dist[2][1] = 9 + 9 = 18. Why these steps? Complete the tour two ways; the expensive branch (18) will lose.- Close: . Why this step? Return edge is also directional — is cheap (3), is dear (9).
Verify: cheap loop ; other loop . DP took 6. ✓
This is why we store dist[i][j] as a full matrix, never assume dist[i][j]==dist[j][i].
Example 4 — Cells D + E: a missing road (∞ edge → unreachable state)
Steps.
dp[011][1] = 4,dp[101][2] = 6. Why this step? Both first hops from 0 exist, so both states are finite.dp[111][2] = dp[011][1] + \text{dist}[1][2] = 4 + \infty = \infty. Why this step? The only way to end at 2 with full mask is via , which doesn't exist — the state is unreachable (Cell E). In code,if dp[mask][i]==INF: continueskips it.dp[111][1] = dp[101][2] + \text{dist}[2][1] = 6 + \infty = \infty. Why this step? Symmetrically dead — ending at 1 needs , also missing.- Close: . Why this step? Both full-mask states are , so the answer is = no valid tour.
Verify: any Hamiltonian cycle on 3 cities uses edge (a triangle has no way to visit all three and close without every edge). Since that edge is missing, no cycle exists. DP correctly returns . ✓ This is the Hamiltonian Path and Cycle existence question surfacing inside the DP for free.
Example 5 — Cell F: Hamiltonian path (no return home)
Steps.
- Reuse the DP table from Example 2 — the internal states are identical; only the final aggregation changes. Why this step? The recurrence never used the return edge, so nothing before the last line differs.
- Path answer .
Why this step? For a path we do not add
dist[i][0]; we just take the cheapest place to end (Mistake #3 handled the other direction).
Verify: path ; path . Cheapest is 30, and (the cycle) as forecast. ✓
Example 6 — Cells G + E: word problem (delivery driver)
Build the matrix (symmetric):
Steps. We evaluate the four candidate delivery orders (with there are tours, but symmetry pairs them into 3 distinct costs — each counted once):
- .
- .
- .
Why these steps? Each row is one full-mask endpoint choice the DP would compare; the DP's
minpicks the smallest. - Answer , route depot→A→B→C→depot. Why this step? The DP's closing line does exactly this comparison automatically.
Verify: minutes, and it beats the others. Units: minutes throughout, no mixing. ✓ (Cell E note: any intermediate dp[mask][i] where bit i isn't in mask stayed and was skipped — same guard as Ex 4.)
Example 7 — Cell H: exam twist, must end at a specific city
Steps.
- Fixed endpoint means the answer is exactly — no minimising over the last city, and no return edge. Why this step? "End at C" removes both the free choice of endpoint and the return term.
- Enumerate orders ending at 3, starting at 0:
- .
- .
Why this step? These are the two ways to arrive at C last; the DP stores the cheaper in
dp[1111][3].
- Answer .
Verify: . It's cheaper than the cycle (18) because we skip the depot edge (cost 4): . Consistent. ✓
Lesson: a fixed end is even easier than a general path — you read one cell, dp[full][target].
Example 8 — Cell I: limiting behaviour & brute-force cross-check
Steps.
- States . Why this step? masks current-city slots — the table's size (see Held-Karp Algorithm).
- Transitions (upper bound; unreachable/illegal states prune this). Why this step? Each state minimises over predecessors — the extra factor .
- Brute force tries full tours. For tiny brute force is fewer operations — DP's win only appears as grows. Why this step? At , ; the exponential-vs-factorial crossover (parent's 80/20) is around and becomes astronomical by .
- Cross-check: brute force over the 6 tours gives costs → min , matching Example 6. Why this step? Two independent methods agreeing is the strongest sanity check (Branch and Bound would prune to the same optimum).
Verify: , , , and the brute-force min DP answer. All confirmed. ✓
Recall Which final line for which question?
Closed tour (cycle) ::: min over i!=0 of dp[full][i] + dist[i][0]
Path, any endpoint ::: min over i of dp[full][i]
Path, fixed endpoint t ::: just dp[full][t] (one cell, no min)
No valid tour exists ::: the chosen expression evaluates to
Connections
- Bitmask DP — TSP intro (index 3.7.15) — parent (state + recurrence built there)
- Travelling Salesman Problem — the problem these examples solve
- Held-Karp Algorithm — the formal name for this DP; complexity in Ex 8
- Dynamic Programming — optimal-substructure backbone
- Bit Manipulation / Subset Enumeration — how masks are indexed
- Hamiltonian Path and Cycle — existence surfaced in Ex 4
- Branch and Bound — alternative exact method (Ex 8 cross-check idea)
- 🇮🇳 3.7.15 Bitmask DP — TSP intro (Hinglish)