5 N/ n/ N$ `1 u4 U$ g" Y3 { }
1 S8 v5 y. f" E1 F, @. ~8 Q
2 }' q: }: Q, H' p; v
) A# x+ P' ^3 R, i% F U
1 H! Q: K" `% ? f) a
/ q0 N) t) g% |8 X- A
8 f8 r( v6 d0 @% p
! B1 p+ ]9 x) v! H' f
- from itertools import permutations2 ^7 Y5 ^- M! _) q. y0 i
- import math, l\" s8 W6 X2 t# d- v+ k
5 o# Q4 h+ M' r+ f3 s; Z6 D4 L2 t. A- def tsp_brute(dist):
\" w( h' u2 b2 ~4 f4 I s2 b - """dist: n×n 距离矩阵,返回 (最短长度, 最优回路)"""
, [1 F. u' f% C2 z& g - n = len(dist)' h4 x) H' E5 S. s5 L
- best_len, best_tour = math.inf, None
8 r, h! }/ ~3 J( M - for perm in permutations(range(1, n)): # 固定起点 0$ b; `1 m, A0 z, l
- tour = [0] + list(perm) P' X0 v; ~: {6 S0 W4 p
- L = sum(dist[tour[i]][tour[i+1]] for i in range(n-1)) + dist[tour[-1]][0]
! v& C/ U; G+ {9 L# C$ F( K - if L < best_len:' g$ Y0 S) r: ]8 e* h
- best_len, best_tour = L, tour
+ q9 L! u# ?& k! [4 X - return best_len, best_tour* e8 o8 k( U* f( O! L\" A2 Y3 `7 S
- ( R, C+ M' q! h$ K( C0 m( n! @
- # ---------- 2-opt 局部搜索(中大规模) ----------7 Q8 F+ @3 w) |4 e }5 K7 D# Z
- def tsp_2opt(dist, max_iter=1000):
' Z( m\" L$ Q7 x! e$ C\" m - n = len(dist)8 T/ Y! d( x# a @3 L8 V: ~5 g
- tour = list(range(n)) # 初始:自然顺序
3 ~3 Z6 n( n% ?$ i2 Z - improved = True
( w6 ~, D0 {2 P5 b% R - while improved and max_iter > 0:1 e, N: Q- z\" j$ V2 ?, b0 s& {3 J
- improved = False4 q, r7 H\" k: u+ M+ T
- for i in range(1, n-2):% E: X3 Q: N$ t% V' N
- for k in range(i+1, n):
: g4 v$ @3 d8 _0 C, C& W7 A7 v1 ]! j! N) @ - # 翻转 tour[i:k+1] X/ {( C4 x1 M( m
- new_tour = tour[:i] + tour[i:k+1][::-1] + tour[k+1:]( {; y0 M3 R3 Z5 q
- cur = sum(dist[tour[j]][tour[j+1]] for j in range(n-1)) + dist[tour[-1]][tour[0]]
+ M7 C- P0 ^8 t* @3 s7 n$ o; K; s - new = sum(dist[new_tour[j]][new_tour[j+1]] for j in range(n-1)) + dist[new_tour[-1]][new_tour[0]]
\" k; s9 p( T; m. }4 Z - if new < cur:/ Q2 z3 `$ K1 r) ]0 h3 I8 B+ O7 T/ Q
- tour, improved = new_tour, True' G3 Q; ~& D\" N7 r: d
- max_iter -= 1
) x, G\" M# t4 L - L = sum(dist[tour[j]][tour[j+1]] for j in range(n-1)) + dist[tour[-1]][tour[0]]
3 l! _+ `4 _- h% u/ S/ {9 w- G M - return L, tour
1 l0 m. l8 v! |' @- K c( n - ; J* v* x( T; a5 [
- # ---------- 测试:4 城市 ----------+ g: m9 M: ?0 w- a
- dist = [
3 U5 |, N: X2 } - [0, 10, 15, 20],
8 ^2 D& U3 t2 x - [10, 0, 35, 25],3 t! V* b0 {9 H% T) a7 h* b, r
- [15, 35, 0, 30],
8 L8 ]5 f4 ~, D6 a - [20, 25, 30, 0]8 K- F# V g+ M1 a; ? |\" ]
- ]. F) h! f8 [0 E
- print("暴力 DFS:", tsp_brute(dist)) # 最短长度 80,回路 0→1→3→2→0
! p: c: P# L0 m - print("2-opt :", tsp_2opt(dist))
复制代码 7.2 运行结果- 暴力 DFS: (80, [0, 1, 3, 2])! S- Q M\" e- _. J8 A' z& ~& a& w
- 2-opt : (95, [0, 1, 2, 3])
复制代码观察:暴力 DFS 保证全局最优( 时可行)。2-opt 从自然顺序出发卡在局部最优 95,未能到达最优解 80——这正是 2-opt 的经典陷阱:单次运行可能陷入局部最优。竞赛中应多次随机重启或结合其他启发式(如先用最近邻初始化再 2-opt)。这也是为什么论文里必须报告"与精确解的 gap",而不是只报一个数字。 8. 竞赛真题映射年份 CUMCM 题目方向 TSP 变体
1 A3 _; _( P6 K- m' C1998B灾情巡视路线巡检 TSP(带时间窗 / 部分覆盖)
: A& m+ l4 S8 j# m& ~6 x2 j2001C公交车线路设计路径规划 + 容量约束(VRP 变体) L$ q( o4 o) N" o' D& G5 Q
2008B啤酒运输问题配送路径优化
, x& h& p3 K! q& |9 r( C1 N2011A高速公路收费站路网遍历 + 费用优化
+ s& x# ]! Q* o; s2015A太阳能小屋设备布点 + 巡检路径% t. y$ n+ i: Z: h
2017B煤炭产量预测无关(数据题)
4 ]3 g7 `+ h- H3 H3 U) ?2020A炉温曲线无关(拟合题)/ m4 G" W9 g6 S! g$ d+ v9 s4 P
近年物流配送 / 应急巡检 / 传感器网络TSP / VRP / 覆盖路径核心规律:只要赛题出现"一条路走遍多个地点",TSP 或其变体(VRP、TSP with Time Windows、多车 TSP)就是最自然的建模原型。先用 TSP 建原型,再根据约束升级为 VRP,是数模竞赛的成熟套路。 9. 常见误区与赛场自查# 误区 正解 : _3 J' P9 ~1 V4 S# P4 I# d5 S
1"TSP 可以用贪心算法精确求解"贪心(最近邻)不保证最优,存在反例
- g0 T) T6 M$ [; R3 b3 D2"2-opt 一定得到全局最优"2-opt 是局部搜索,可能陷入局部最优8 m% ]- ]+ ?4 \' r6 V
3"TSP 和指派问题等价"TSP 要求单一回路,指派问题允许子回路
9 Z. f, |- P6 I$ X" ?# q) `0 h4"子回路消除约束可以一次性写完"数量 级别,实际用逐步加入(lazy constraint)% Z; K! b# E R* U# g
5"DP 复杂度 "准确是 ,每状态需 转移; r+ | R4 B* s7 H% o! ~$ Q/ y
6"所有 TSP 都有常数近似比"仅度量 TSP(三角不等式)有 Christofides 近似
, N3 F+ J& I) _- X# i3 ^; k7"对称 TSP 和非对称 TSP 一样"对称: 种回路;非对称: 种赛场自查清单: - 我确认了距离矩阵是否对称、是否满足三角不等式(影响算法选择)。
- 我估计了可行解数量 ,判断暴力 / B&B / 启发式的适用性。
- 若用 B&B:下界函数是否安全(不高于最优值)且紧?
- 若用 2-opt:是否报告了与精确解的偏差(小规模对比)?
- 若用 Christofides:是否验证了三角不等式成立?
- 论文中是否报告了运行时间与最优性差距(gap)?
- 是否对结果做了敏感性分析(距离矩阵微调时回路是否稳定)?
- 是否给出了子回路消除的处理方式(lazy constraint 或逐步加入)?0 L; [$ R) s# T" r# J
10. 参考文献[1] Dantzig, G. B., Fulkerson, D. R., & Johnson, S. M. (1954). Solution of a Large-Scale Traveling-Salesman Problem. Operations Research, 2(4), 393–410. DOI: 10.1287/opre.2.4.393. https://doi.org/10.1287/opre.2.4.393 [2] Held, M., & Karp, R. M. (1961). A dynamic programming approach to sequencing problems. Proceedings of the 1961 16th ACM National Meeting, pp. 71.201–71.204. DOI: 10.1145/800029.808532. https://doi.org/10.1145/800029.808532 [3] Held, M., & Karp, R. M. (1962). The traveling-salesman problem and minimum spanning trees: Part II. Operations Research, 18(6), 1138–1162. DOI: 10.1287/opre.18.6.1138. [4] Lawler, E. L., Lenstra, J. K., Rinnooy Kan, A. H. G., & Shmoys, D. B. (Eds.) (1985). The Traveling Salesman Problem: A Guided Tour of Combinatorial Optimization. Wiley-Interscience Series in Discrete Mathematics, Vol. 12. Chichester: John Wiley & Sons. ISBN 978-0-471-90413-7. [5] Applegate, D. L., Bixby, R. E., Chvátal, V., & Cook, W. J. (2011). The Traveling Salesman Problem: A Computational Study. Princeton Series in Applied Mathematics. Princeton, NJ: Princeton University Press. ISBN 978-0-691-12993-8 (print), 978-1-400-84110-3 (ebook). https://press.princeton.edu/books/ebook/9781400841103/the-traveling-salesman-problem-pdf [6] Cook, W. (2012). In Pursuit of the Traveling Salesman: Mathematics at the Limits of Computation. Princeton, NJ: Princeton University Press. ISBN 978-0-691-16352-9. [7] 姜启源, 谢金星, 叶俊. 数学模型. 5版. 北京: 高等教育出版社, 2018. ISBN 978-7-04-049222-4. [8] 司守奎, 孙玺菁. 数学建模算法与应用. 3版. 北京: 国防工业出版社, 2021. ISBN 978-7-118-12278-7. [9] 胡运权, 主编. 运筹学教程. 5版. 北京: 清华大学出版社, 2018. ISBN 978-7-302-48125-6. https://www.tup.tsinghua.edu.cn/wap/tsxqy.aspx?id=07656604 给参赛学生的一句话:TSP 是数模优化题里"最简单的难题"——问题描述一句话,求解却需要一整套组合优化工具箱。小规模用 B&B/DP 保证最优,大规模用 2-opt 给出好解并报告 gap,这是评委最认可的"务实"策略。记住:能证明最优的解,比看似漂亮但无保证的解更有说服力。
5 P4 H$ b7 g8 b! O8 A7 Z1 @6 Z8 M% Y' {4 R( I2 J
|