2 i, @6 v2 M2 l& }9 F6 R
- R; z3 {# q$ a8 A3 c$ j
; h5 n7 O8 Y% L2 c
# Y& h' L9 Y' L% i8 @+ N
h: P1 h# M% S% \6 F( D9 y3 L
- @* O! g6 R. | _$ H
2 C$ E2 t1 v8 @# I9 w- _5 T
' |. E' K r4 v9 p! ~+ ^4 f
- from itertools import permutations
, V X' V+ _. E2 L; U1 U; G0 t; Q% m - import math# R7 A& f. i' s
3 N6 {# t q, q! E- def tsp_brute(dist):. V: ]3 x/ q8 M4 B
- """dist: n×n 距离矩阵,返回 (最短长度, 最优回路)"""2 b5 ^+ y5 N6 l3 L- L* D; A
- n = len(dist)
S8 t \- A# w\" Q, C* U - best_len, best_tour = math.inf, None' `6 y5 a6 g& j8 Y6 ]* m
- for perm in permutations(range(1, n)): # 固定起点 01 D% [\" t# C2 R
- tour = [0] + list(perm)2 k$ l5 g: M! N4 V0 k
- L = sum(dist[tour[i]][tour[i+1]] for i in range(n-1)) + dist[tour[-1]][0]$ h- p7 ^2 I+ B1 g3 m5 [ z
- if L < best_len:, O1 r) c6 E2 g S; w
- best_len, best_tour = L, tour0 g& q6 J& b8 ]7 e\" o* e8 H
- return best_len, best_tour
: `) K2 |* S1 R6 B) Z- c
& [! Q+ v% Z\" e$ K5 D& _3 [- # ---------- 2-opt 局部搜索(中大规模) ----------: R& A9 b/ o! B( h0 K\" D
- def tsp_2opt(dist, max_iter=1000):6 S1 v! C S! ^% e, |, y D
- n = len(dist)7 v/ ?\" E- [6 N) E4 k
- tour = list(range(n)) # 初始:自然顺序* l- P/ G G$ l' P) y7 K! }0 z
- improved = True
7 u0 ~5 R* U& j+ r5 r0 i - while improved and max_iter > 0:) N ]- \$ Q$ ^2 }7 S( c
- improved = False
( f# }, t, y; ? - for i in range(1, n-2):- B* u! {% o$ Z/ h9 K- ?+ m, i# D) J
- for k in range(i+1, n): O L. |( O/ [$ O+ ^# b$ l
- # 翻转 tour[i:k+1]
; v* | W/ `# q3 x1 N - new_tour = tour[:i] + tour[i:k+1][::-1] + tour[k+1:]
, o/ I+ V; d/ {1 b - cur = sum(dist[tour[j]][tour[j+1]] for j in range(n-1)) + dist[tour[-1]][tour[0]]
4 r: N4 @5 N5 t5 q - new = sum(dist[new_tour[j]][new_tour[j+1]] for j in range(n-1)) + dist[new_tour[-1]][new_tour[0]]
5 I( ^6 o\" Z% W) X% A, H7 Z - if new < cur:
6 D: F: `+ c2 D) X6 V: J+ I - tour, improved = new_tour, True
3 j1 r1 K7 y( T8 F' k9 ?) N1 f - max_iter -= 1 H\" f; O$ E u3 s
- L = sum(dist[tour[j]][tour[j+1]] for j in range(n-1)) + dist[tour[-1]][tour[0]]
; @: k: N+ \+ O - return L, tour
2 m, c: _! Y8 y* ]
2 `\" ?! R! \7 T' C- # ---------- 测试:4 城市 ----------
6 j\" k& V: I* x* T+ a - dist = [/ Z: V, c% U! c7 Y1 C9 C! D: I
- [0, 10, 15, 20],& Y2 r5 l5 \& A\" v4 C
- [10, 0, 35, 25],+ U3 q' V8 E' H5 w$ X, y! K
- [15, 35, 0, 30],( E, o y! {( a6 X2 Y
- [20, 25, 30, 0]
4 I& \1 p8 {: F8 l) [; C3 o g - ]
6 \1 {# _# V( u' Q( @0 ]\" v0 I - print("暴力 DFS:", tsp_brute(dist)) # 最短长度 80,回路 0→1→3→2→0
b2 }$ r+ A) E, {: ~' j1 n - print("2-opt :", tsp_2opt(dist))
复制代码 7.2 运行结果- 暴力 DFS: (80, [0, 1, 3, 2])2 z1 f\" y9 [4 ]: O
- 2-opt : (95, [0, 1, 2, 3])
复制代码观察:暴力 DFS 保证全局最优( 时可行)。2-opt 从自然顺序出发卡在局部最优 95,未能到达最优解 80——这正是 2-opt 的经典陷阱:单次运行可能陷入局部最优。竞赛中应多次随机重启或结合其他启发式(如先用最近邻初始化再 2-opt)。这也是为什么论文里必须报告"与精确解的 gap",而不是只报一个数字。 8. 竞赛真题映射年份 CUMCM 题目方向 TSP 变体 # A+ C$ t% B6 h* Y, F K
1998B灾情巡视路线巡检 TSP(带时间窗 / 部分覆盖) ~8 s8 r6 q- l5 l+ z: C/ n
2001C公交车线路设计路径规划 + 容量约束(VRP 变体)" d9 p4 h! }5 g- ~0 l9 [. ~
2008B啤酒运输问题配送路径优化
1 B4 ]6 ?3 _# G# O+ f2011A高速公路收费站路网遍历 + 费用优化( M& a* x2 ^) ?# x v8 j/ f
2015A太阳能小屋设备布点 + 巡检路径
& K8 m y1 h# R e* K4 D2017B煤炭产量预测无关(数据题)' ?9 ~2 U# S/ H' e' I( O
2020A炉温曲线无关(拟合题)
' s. P9 Y: R, S) Y- a1 P# `* a' X近年物流配送 / 应急巡检 / 传感器网络TSP / VRP / 覆盖路径核心规律:只要赛题出现"一条路走遍多个地点",TSP 或其变体(VRP、TSP with Time Windows、多车 TSP)就是最自然的建模原型。先用 TSP 建原型,再根据约束升级为 VRP,是数模竞赛的成熟套路。 9. 常见误区与赛场自查# 误区 正解 - Q: i7 P) V5 g
1"TSP 可以用贪心算法精确求解"贪心(最近邻)不保证最优,存在反例# S1 G* J5 U( Q6 y* }5 X6 q
2"2-opt 一定得到全局最优"2-opt 是局部搜索,可能陷入局部最优
9 V7 M# G9 T' w1 T3 C3"TSP 和指派问题等价"TSP 要求单一回路,指派问题允许子回路
& y( _2 C( K4 y4"子回路消除约束可以一次性写完"数量 级别,实际用逐步加入(lazy constraint)# f9 y8 c1 V$ Z- p
5"DP 复杂度 "准确是 ,每状态需 转移
1 I6 P! W. L( ~- w! F" c" U/ Y6"所有 TSP 都有常数近似比"仅度量 TSP(三角不等式)有 Christofides 近似- ]! N' q& {; d/ o; F" h) Y, p
7"对称 TSP 和非对称 TSP 一样"对称: 种回路;非对称: 种赛场自查清单: - 我确认了距离矩阵是否对称、是否满足三角不等式(影响算法选择)。
- 我估计了可行解数量 ,判断暴力 / B&B / 启发式的适用性。
- 若用 B&B:下界函数是否安全(不高于最优值)且紧?
- 若用 2-opt:是否报告了与精确解的偏差(小规模对比)?
- 若用 Christofides:是否验证了三角不等式成立?
- 论文中是否报告了运行时间与最优性差距(gap)?
- 是否对结果做了敏感性分析(距离矩阵微调时回路是否稳定)?
- 是否给出了子回路消除的处理方式(lazy constraint 或逐步加入)?% J9 b0 f a1 L0 P! F
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,这是评委最认可的"务实"策略。记住:能证明最优的解,比看似漂亮但无保证的解更有说服力。 3 h1 K& ]7 G E2 O& m) x
9 \/ D9 L" a) d- D2 H# f
|