💡 DP keeps track of minimum cost among multiple paths to the same state.
fill_row
Process Full Subset mask=15 (all cities visited)
Process full subset mask=15 (all cities visited). Consider paths ending at cities 2 and 3 to return to city 0.
💡 Preparing to compute the final answer by considering all full visits.
Line:for i in range(1, n):
ans = min(ans, dp[ALL_VISITED][i] + dist[i][0])
💡 Final answer is minimum cost to visit all cities and return to start.
reconstruct
Calculate Final Answer
Compute minimum cost to complete the tour by returning to city 0 from each possible ending city, choosing the minimum total cost.
💡 Extract the answer from the DP table by adding return cost to start city.
Line:ans = float('inf')
for i in range(1, n):
ans = min(ans, dp[ALL_VISITED][i] + dist[i][0])
return ans
💡 DP table contains all partial solutions; final answer combines them with return cost.
reconstruct
Output Final Result
Return the minimum cost 80, representing the shortest route visiting all cities and returning to start.
💡 Confirms the DP approach solves the TSP for the input.
Line:return ans
💡 DP table and bitmasking efficiently solve the exponential TSP problem.
def tsp_bottom_up(dist):
n = len(dist) # STEP 1
ALL_VISITED = (1 << n) - 1 # STEP 1
dp = [[float('inf')] * n for _ in range(1 << n)] # STEP 1
dp[1][0] = 0 # STEP 1
for mask in range(1 << n): # STEP 2
for i in range(n): # STEP 2
if mask & (1 << i): # STEP 2
for j in range(n): # STEP 3
if not (mask & (1 << j)): # STEP 3
new_mask = mask | (1 << j) # STEP 3
dp[new_mask][j] = min(dp[new_mask][j], dp[mask][i] + dist[i][j]) # STEP 3
ans = float('inf') # STEP 13
for i in range(1, n): # STEP 13
ans = min(ans, dp[ALL_VISITED][i] + dist[i][0]) # STEP 14
return ans # STEP 15
if __name__ == '__main__':
dist = [[0,10,15,20],[10,0,35,25],[15,35,0,30],[20,25,30,0]]
print(tsp_bottom_up(dist)) # Output: 80
📊
Travelling Salesman (Bitmask DP) - Watch the Algorithm Execute, Step by Step
Watching this visualization helps you understand how bitmasking encodes subsets and how the DP table builds solutions from smaller subsets to larger ones, which is hard to grasp from code alone.
Step 1/15
·Active fill★Answer cell
Item 0 - wt:0 val:0
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
?
?
?
i=4
?
?
?
?
i=5
?
?
?
?
i=6
?
?
?
?
i=7
?
?
?
?
i=8
?
?
?
?
i=9
?
?
?
?
i=10
?
?
?
?
i=11
?
?
?
?
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
start=0 cost=0
Item 0 - wt:0 val:0
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
?
?
?
i=4
?
?
?
?
i=5
?
?
?
?
i=6
?
?
?
?
i=7
?
?
?
?
i=8
?
?
?
?
i=9
?
?
?
?
i=10
?
?
?
?
i=11
?
?
?
?
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
processing mask=1 city=0
Item 0 - wt:0 val:0
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
?
?
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
?
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
cost=10 from 0->1
Item 1 - wt:0 val:10
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
?
?
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
processing mask=3 city=1
Item 1 - wt:0 val:10
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
?
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
cost=45 from 1->2
Item 1 - wt:0 val:10
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
?
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
cost=35 from 1->3
Item 2 - wt:0 val:15
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
?
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
processing mask=5 city=2
Item 2 - wt:0 val:15
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
cost=50 from 2->1
Item 2 - wt:0 val:45
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
?
processing mask=7 city=2
Item 2 - wt:0 val:45
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
75
cost=75 from 2->3
Item 3 - wt:0 val:35
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
?
75
processing mask=11 city=3
Item 3 - wt:0 val:35
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
65
75
cost=65 from 3->2
Item 2 - wt:0 val:65
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
65
75
full visit ending at city 2
Item 2 - wt:0 val:65
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
65
75
final answer cell
Item 2 - wt:0 val:65
i\w
0
1
2
3
i=0
?
?
?
?
i=1
0
?
?
?
i=2
?
?
?
?
i=3
?
10
?
?
i=4
?
?
?
?
i=5
?
?
15
?
i=6
?
?
?
?
i=7
?
50
45
?
i=8
?
?
?
?
i=9
?
?
?
20
i=10
?
?
?
?
i=11
?
?
?
35
i=12
?
?
?
?
i=13
?
?
?
?
i=14
?
?
?
?
i=15
?
?
65
75
final answer = 80
Key Takeaways
✓ Bitmasking efficiently encodes subsets of visited cities, enabling compact DP state representation.
This insight is hard to see from code alone because bitmask operations are abstract; visualization shows subsets explicitly.
✓ DP table entries represent minimum cost to reach a city with a specific subset visited, building solutions bottom-up.
Seeing the table fill in order clarifies dependencies and why smaller subsets must be solved first.
✓ Multiple paths can lead to the same subset and city, but the DP table always keeps the minimum cost.
The visualization highlights cost updates, showing how the algorithm optimizes among alternatives.
Practice
(1/5)
1. Consider the following code snippet for counting arithmetic subsequences. What is the final returned value when the input is [1, 3, 5]?
Total after all iterations is 1, representing one arithmetic subsequence of length ≥ 3: [1,3,5].
Final Answer:
Option A -> Option A
Quick Check:
Only one arithmetic subsequence of length ≥ 3 exists [OK]
Hint: Only subsequences length ≥3 count; pairs add to dp but not total [OK]
Common Mistakes:
Counting pairs as arithmetic subsequences
Adding dp[i][diff] to total instead of dp[j][diff]
2. What is the time complexity of the space optimized bitmask DP solution for counting ways to assign unique caps to n people, where caps range up to 100 and each person has a list of caps they can wear?
medium
A. O(n * 2^n)
B. O(100 * 2^n * n)
C. O(2^n * n^2)
D. O(n * 100^n)
Solution
Step 1: Identify loops in the algorithm
The outer loop iterates over caps (up to 100), the middle loop iterates over all masks (2^n), and the inner loop iterates over persons (up to n) who can wear the current cap.
Step 2: Combine loop complexities
Multiplying these gives O(100 * 2^n * n). Other options either omit the cap factor or incorrectly exponentiate caps.
Final Answer:
Option B -> Option B
Quick Check:
Counting all masks and caps with person checks matches O(100 * 2^n * n) [OK]
Hint: Count loops: caps * masks * persons per cap [OK]
Common Mistakes:
Ignoring caps loop
Confusing n with cap count
Forgetting inner loop over persons
3. Consider the following buggy code for the House Robber III problem. Which line contains the subtle bug that causes incorrect results on some inputs?
def rob(root):
def dfs(node):
if not node:
return (0, 0) # (not_rob, rob)
left = dfs(node.left)
right = dfs(node.right)
rob_node = node.val + left[1] + right[1] # Bug here
not_rob_node = max(left) + max(right)
return (not_rob_node, rob_node)
return max(dfs(root))
medium
A. Line returning max of dfs(root) instead of sum
B. Line computing rob_node sums children rob values instead of not_rob values
C. Line returning (not_rob_node, rob_node) tuple instead of single value
D. Line checking if node is null and returning (0,0)
Solution
Step 1: Understand rob_node calculation
When robbing current node, children cannot be robbed, so we must add left[0] and right[0] (not_rob values).
Step 2: Identify bug
The code incorrectly adds left[1] and right[1] (rob values), causing double counting and invalid solutions.
4. What is the time complexity of the optimized LIS algorithm using binary search on an input array of length n?
medium
A. O(n log n)
B. O(n)
C. O(n²)
D. O(log n)
Solution
Step 1: Identify outer loop complexity
The algorithm iterates over all n elements once, so at least O(n).
Step 2: Identify inner operation complexity
For each element, binary search on tails array takes O(log n) time.
Final Answer:
Option A -> Option A
Quick Check:
n iterations x log n binary search -> O(n log n) [OK]
Hint: Binary search inside loop gives n log n [OK]
Common Mistakes:
Assuming O(n²) because of nested loops
Ignoring binary search complexity
Confusing with brute force exponential
5. Examine the following buggy code snippet for shortest path visiting all nodes. Which line contains the subtle bug that can cause incorrect results or infinite loops?
medium
A. Line setting base cases: dp[i][1 << i] = 0
B. Line updating next_mask: next_mask = mask ^ (1 << v)
C. Line with dp initialization: dp = [[float('inf')] * (1 << n) for _ in range(n)]
D. Line updating dp[v][next_mask]: dp[v][next_mask] = dp[u][mask] + 1
Solution
Step 1: Identify how visited nodes are tracked
Visited nodes are represented by a bitmask. To add a visited node, bitwise OR (|) must be used.
Step 2: Spot the incorrect bitmask operation
The code uses XOR (^) instead of OR (|) to update next_mask, which can incorrectly unset bits and cause wrong states or infinite loops.
Final Answer:
Option B -> Option B
Quick Check:
Using XOR breaks the visited set semantics [OK]
Hint: Visited mask update must use OR, not XOR [OK]
Common Mistakes:
Using XOR instead of OR for mask update
Forgetting to initialize dp base cases
Not checking dp[u][mask] == inf before continuing
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.