1
1
#!/usr/bin/env python3
2
2
3
+
3
4
def tsp (distances : list [list [int ]]) -> int :
4
5
"""
5
- Solves the Travelling Salesman Problem (TSP)
6
- using dynamic programming and bitmasking.
7
-
8
- Args:
9
- distances: 2D list where distances[i][j]
10
- is the distance between city i and city j.
11
-
12
- Returns:
13
- Minimum cost to complete the tour visiting all cities.
14
-
15
- Raises:
16
- ValueError: If any distance is negative.
17
-
18
- >>> tsp([[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]])
19
- 80
20
- >>> tsp([[0, 29, 20, 21], [29, 0, 15, 17], [20, 15, 0, 28], [21, 17, 28, 0]])
21
- 69
22
- >>> tsp([[0, 10, -15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]])
23
- # doctest: +ELLIPSIS
24
- Traceback (most recent call last):
25
- ...
26
- ValueError: Distance cannot be negative
6
+ Solves the Travelling Salesman Problem (TSP)
7
+ using dynamic programming and bitmasking.
8
+
9
+ Args:
10
+ distances: 2D list where distances[i][j]
11
+ is the distance between city i and city j.
12
+
13
+ Returns:
14
+ Minimum cost to complete the tour visiting all cities.
15
+
16
+ Raises:
17
+ ValueError: If any distance is negative.
18
+
19
+ >>> tsp([[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]])
20
+ 80
21
+ >>> tsp([[0, 29, 20, 21], [29, 0, 15, 17], [20, 15, 0, 28], [21, 17, 28, 0]])
22
+ 69
23
+ >>> tsp([[0, 10, -15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]])
24
+ # doctest: +ELLIPSIS
25
+ Traceback (most recent call last):
26
+ ...
27
+ ValueError: Distance cannot be negative
27
28
"""
28
29
n = len (distances )
29
30
if any (distances [i ][j ] < 0 for i in range (n ) for j in range (n )):
@@ -40,7 +41,7 @@ def visit(city: int, mask: int) -> int:
40
41
if memo [city ][mask ] != - 1 : # Return cached result if exists
41
42
return memo [city ][mask ]
42
43
43
- min_cost = float (' inf' ) # Use infinity for initial comparison
44
+ min_cost = float (" inf" ) # Use infinity for initial comparison
44
45
for next_city in range (n ):
45
46
if not (mask & (1 << next_city )): # If unvisited
46
47
new_cost = distances [city ][next_city ] + visit (
@@ -49,8 +50,11 @@ def visit(city: int, mask: int) -> int:
49
50
min_cost = min (min_cost , new_cost )
50
51
memo [city ][mask ] = min_cost # Store result in the memoization table
51
52
return min_cost
53
+
52
54
return visit (0 , 1 ) # Start from city 0 with only city 0 visited
53
55
56
+
54
57
if __name__ == "__main__" :
55
58
import doctest
59
+
56
60
doctest .testmod ()
0 commit comments