import sys
def tsp(distances):
n = len(distances)
all_points_set = set(range(n))
# memo keys: tuple(sorted_points_in_path, last_point_in_path)
# memo values: tuple(cost_thus_far, next_to_last_point_in_path)
memo = {(tuple([i]), i): tuple([0, None]) for i in range(n)}
queue = [(tuple([i]), i) for i in range(n)]
while queue:
prev_visited, prev_last_point = queue.pop(0)
prev_dist, _ = memo[(prev_visited, prev_last_point)]
to_visit = all_points_set.difference(set(prev_visited))
for new_last_point in to_visit:
new_visited = tuple(sorted(list(prev_visited) + [new_last_point]))
new_dist = prev_dist + distances[prev_last_point][new_last_point]
if (new_visited, new_last_point) not in memo:
queue += [(new_visited, new_last_point)]
memo[(new_visited, new_last_point)] = min(
memo.get((new_visited, new_last_point), (float('inf'), None)),
(new_dist, prev_last_point))
optimal_path, optimal_cost = retrace_optimal_path(memo, n)
return optimal_path, optimal_cost
def retrace_optimal_path(memo: dict, n: int) -> [[int], float]:
points_to_retrace = tuple(range(n))
full_path_memo = dict((k, v) for k, v in memo.items() if k[0] == points_to_retrace)
path_key = min(full_path_memo.keys(), key=lambda x: full_path_memo[x][0])
last_point = path_key[1]
optimal_cost, next_to_last_point = memo[path_key]
optimal_path = [last_point]
points_to_retrace = tuple(sorted(set(points_to_retrace).difference({last_point})))
while next_to_last_point is not None:
path_key = (points_to_retrace, next_to_last_point)
_, next_to_last_point = memo[path_key]
optimal_path = [path_key[1]] + optimal_path
points_to_retrace = tuple(sorted(set(points_to_retrace).difference({path_key[1]})))
return optimal_path, optimal_cost
在这段代码中,distances是一个二维数组,表示每两个城市之间的距离。tsp函数返回一个元组,第一个元素是一个列表,表示最优路径(城市的顺序),第二个元素是这个路径的总成本。
这个算法的时间复杂度是O(n^2 * 2^n),空间复杂度是O(n * 2^n)。这是因为算法需要枚举所有可能的路径,并且需要记住之前计算过的路径的成本。其中,n是城市的数量。
请注意,这个算法假设距离矩阵是对称的,也就是说,从城市A到城市B的距离和从城市B到城市A的距离是相同的。如果这个假设不成立,那么你需要修改这个算法,使其可以处理这种情况。
|