当前位置:首页>python>旅行商问题:从数学模型到 Python 实战

旅行商问题:从数学模型到 Python 实战

  • 2026-10-11 07:30:10
旅行商问题:从数学模型到 Python 实战
点击上方蓝字订阅!

旅行商问题(Traveling Salesman Problem, TSP)是组合优化领域中一颗璀璨的明珠,也是计算机科学中 NP-hard 问题的典型代表。其问题描述简洁而优雅:给定  个城市以及两两之间的距离 ,求解一条从某一城市出发,恰好访问每个城市一次并最终返回起点的最短哈密顿回路。尽管表述简单,但随着城市数量的增加,其解空间呈阶乘级增长,使得寻找最优解成为一项极具挑战性的任务。

从数学角度看,TSP 可以被形式化为在一个带权完全图中寻找最小权重的哈密顿回路。设城市集合为 ,距离函数为 ,我们的目标是最小化路径总长度 ,即:

其中  是城市的一个排列,且 。由于 TSP 的复杂度极高(时间复杂度约为 ),对于大规模实例,精确算法往往无能为力,因此工程实践中常采用启发式算法寻求近似最优解。

为了将理论落地,我们考虑一个具体的对称 TSP 实例。假设有 4 个城市 ,它们之间的距离矩阵  定义如下:

该矩阵是对称的,即 ,且对角线为 0,符合欧几里得空间的基本直觉。

针对此问题,我们首先实现暴力枚举法(Brute Force)。该方法通过遍历所有可能的城市排列(Permutation)来寻找全局最优解。虽然这种方法的时间复杂度为 ,仅适用于小规模问题,但它保证了结果的绝对精确。以下是 Python 实现:

import itertools
import math

# 城市节点
cities = ['A', 'B', 'C', 'D']

# 距离字典(邻接表形式)
dist = {
    ('A','A'): 0,   ('A','B'): 10,  ('A','C'): 15,  ('A','D'): 20,
    ('B','A'): 10,  ('B','B'): 0,   ('B','C'): 35,  ('B','D'): 25,
    ('C','A'): 15,  ('C','B'): 35,  ('C','C'): 0,   ('C','D'): 30,
    ('D','A'): 20,  ('D','B'): 25,  ('D','C'): 30,  ('D','D'): 0
}

defcalculate_path_length(path):
"""计算路径总长度"""
    total = 0
for i in range(len(path) - 1):
        total += dist[(path[i], path[i+1])]
    total += dist[(path[-1], path[0])]  # 回到起点
return total

# 固定起点为 A,对其他城市进行全排列
start_node = 'A'
other_nodes = [city for city in cities if city != start_node]

optimal_path = None
min_distance = math.inf

# 遍历所有排列组合
for perm in itertools.permutations(other_nodes):
    current_path = (start_node,) + perm
    current_dist = calculate_path_length(current_path)
if current_dist < min_distance:
        min_distance = current_dist
        optimal_path = current_path

print(f"最优路径(精确解): {optimal_path}")
print(f"最短距离: {min_distance}")

运行上述代码,我们可以得到最优路径为 ,总距离为 。

然而,当城市数量增加到 20 个以上时,暴力枚举将消耗天文数字的时间。此时,我们需要转向启发式算法。这里我们实现最近邻算法(Nearest Neighbor),这是一种贪婪策略:每一步都选择距离当前城市最近的未访问城市。虽然它不能保证最优,但其时间复杂度仅为 ,速度极快。

# 城市列表
cities = {'A', 'B', 'C', 'D'}

# 距离映射(必须包含所有城市对)
dist = {
    ('A', 'B'): 10, ('B', 'A'): 10,
    ('A', 'C'): 15, ('C', 'A'): 15,
    ('A', 'D'): 20, ('D', 'A'): 20,
    ('B', 'C'): 35, ('C', 'B'): 35,
    ('B', 'D'): 25, ('D', 'B'): 25,
    ('C', 'D'): 30, ('D', 'C'): 30,
}

defcalculate_path_length(route):
"""计算路径总距离"""
    total = 0
for i in range(len(route) - 1):
        total += dist[(route[i], route[i + 1])]
# 可选:回到起点
    total += dist[(route[-1], route[0])]
return total

defnearest_neighbor_tsp(start, distance_map):
"""最近邻启发式求解 TSP"""
    unvisited = set(cities)
    route = [start]
    unvisited.remove(start)

    current_city = start
while unvisited:
        next_city = min(
            unvisited,
            key=lambda city: distance_map[(current_city, city)]
        )
        route.append(next_city)
        unvisited.remove(next_city)
        current_city = next_city

return route


# 执行最近邻算法
nn_route = nearest_neighbor_tsp('A', dist)
nn_distance = calculate_path_length(nn_route)

print(f"最近邻路径: {nn_route}")
print(f"最近邻距离: {nn_distance}")

在本例中,最近邻算法同样输出了  的最优解,但在更复杂的数据集中,结果通常会略逊于最优解。这种权衡体现了算法设计中“时间”与“精度”的经典博弈。对于更大规模的现实问题,我们往往需要引入更复杂的元启发式算法(如遗传算法、模拟退火)或使用 Google OR-Tools 等专业优化库。TSP 不仅是理论的试金石,更是物流配送、电路板钻孔、基因测序等众多实际应用的核心模型。

 • end • 

陪伴是最长情的告白

 为你推送最实用的资讯 

识别二维码 关注我们 

最新文章

随机文章