3.7.15 · D3Algorithm Paradigms

Worked examples — Bitmask DP — TSP intro

2,381 words11 min readBack to topic

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.

  1. 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 .
  2. Reach city 1: dp[11][1] = dp[01][0] + dist[0][1] = 0 + 7 = 7. Why this step? mask=11 means visited; to end at 1 we peel the last edge .
  3. 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.

Figure — Bitmask DP — TSP intro

Steps.

  1. 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.
  2. 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.
  3. 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.
  4. 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.

  1. 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.
  2. dp[111][2] = dp[011][1] + dist[1][2] = 1 + 2 = 3.
  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.
  4. 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.

  1. dp[011][1] = 4, dp[101][2] = 6. Why this step? Both first hops from 0 exist, so both states are finite.
  2. 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: continue skips it.
  3. dp[111][1] = dp[101][2] + \text{dist}[2][1] = 6 + \infty = \infty. Why this step? Symmetrically dead — ending at 1 needs , also missing.
  4. 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.

  1. 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.
  2. 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):

  1. .
  2. .
  3. . Why these steps? Each row is one full-mask endpoint choice the DP would compare; the DP's min picks the smallest.
  4. 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.

  1. 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.
  2. 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].
  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.

  1. States . Why this step? masks current-city slots — the table's size (see Held-Karp Algorithm).
  2. Transitions (upper bound; unreachable/illegal states prune this). Why this step? Each state minimises over predecessors — the extra factor .
  3. 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 .
  4. 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)