交互式图论学习
交互式图论学习
Guest User
Using app without sign in
在线旅行商问题求解器
找到恰好访问所有顶点一次的最短旅程
选择算法并生成步骤以开始可视化
旅行商问题(TSP)求恰好访问每个城市一次并返回起点的最短巡回路线。它是组合优化中最著名的 NP 难问题,陈述简单却在精确求解上呈指数级困难。
Held-Karp 动态规划解法为每个城市子集和每个终点城市存储访问该子集的最便宜方式。每个状态一次扩展一个未访问城市,时间为 O(n 的平方乘以 2 的 n 次方),精确但仅对约 20 个城市可行。更大的实例依赖最近邻和 2-opt 等启发式,或元启发式和分支定界求解器,为数千城市得到接近最优的巡回。
TSP 建模配送路线规划、仓库拣货、电路板钻孔、DNA 序列组装以及望远镜观测排程。它是研究 NP 完全性和近似算法的核心,面试官用它来考查对复杂度类和位掩码动态规划的理解。
旅行商问题没有快速的精确算法,因此务实的做法分两个阶段:先快速构造一条尚可的回路,再做局部改进直到无法继续为止。
// 阶段一:最近邻,以 O(n^2) 构造一条回路
回路 = [起点]
当仍有城市未访问时:
下一个 = 距回路末端最近的未访问城市
回路.追加(下一个)
回路.追加(起点) // 闭合回路
// 阶段二:2-opt,消除交叉直到无改进
重复直到没有改进:
对回路中每一对边 (a,b) 与 (c,d):
若 dist(a,c) + dist(b,d) < dist(a,b) + dist(c,d):
反转 b 与 c 之间的回路片段
// 精确解,n 较小时:Held-Karp 动态规划
dp[S][j] = 对 S\{j} 中的 k 取 dp[S\{j}][k] + dist(k, j) 的最小值2-opt 这一步值得从几何角度理解。若回路中两条边相交,交换它们的端点并反转中间片段,依据三角不等式必然缩短回路。因此 2-opt 字面意义上就是把一根绳圈上的结解开。
对矩形四角上的四座城市先跑最近邻再跑 2-opt,这里贪心选择可能明显出错。
示例图: 城市 A(0,0)、B(0,3)、C(4,3)、D(4,0)。距离:A-B 3、B-C 4、C-D 3、A-D 4,两条对角线 A-C 与 B-D 均为 5。
最优回路是代价 14 的矩形周长,而不是代价 18 的任何一条含交叉对角线的回路。这就是 TSP 启发式算法的缩影:一次快速的构造性扫描已经很接近,局部搜索再把贪心选择引入的交叉消除掉。
时间: 启发式 O(n^2),精确 O(n^2 · 2^n) · 空间: 启发式 O(n^2),精确 O(n · 2^n)
最近邻在 n 个步骤中每一步都扫描全部剩余城市,因此为 O(n 的平方)。每一轮 2-opt 检验全部 O(n 的平方) 对边并反复进行直到无改进,实践中很快,但最坏情况没有有用的上界。Held-Karp 是精确算法,其表以子集与端点为索引:共有 2 的 n 次方个子集乘以 n 个端点,每个表项花费 O(n),因此时间为 O(n 的平方乘以 2 的 n 次方),内存为 O(n 乘以 2 的 n 次方)。这在 n = 20 到 25 附近就是一堵硬墙,因为 2 的 25 次方乘以 25 已超过十亿个表项。对全部排列做暴力枚举更糟,为 O(n 的阶乘)。
选用哪种方法几乎完全取决于城市数量,以及你是否需要可证明的最优解。
| 替代算法 | 以下情况更合适 | 代价 |
|---|---|---|
| Held-Karp 精确动态规划 | 城市数少于约 20,且你需要保证最优的回路。 | O(n^2 · 2^n) |
| Christofides 算法 | 距离满足三角不等式,且你需要一个已证明的上界:不劣于最优解的 1.5 倍。 | O(n^3) |
| 最近邻加 2-opt | 数百到数千座城市,且与最优解相差几个百分点即可接受。 | 每轮 O(n^2) |
| Lin-Kernighan 算法 | 大规模实例,质量比实现难度更重要。这是实践中的最高水准。 | 约 O(n^2.2) |
| 车辆路径求解器 | 真实问题涉及多台车辆、载重或时间窗。那时它根本就不是 TSP。 | 视情况而定 |
阅读完整文章: The Traveling Salesperson Problem Explained
相关算法: 哈密顿路径, 车队调度 (mTSP), 带容量限制的车辆路径规划 (CVRP)