1 F" s+ t5 {$ h0 [
6 B3 [9 g( X8 C# T/ K2 l9 X, ?4 i+ R# h
9 c; \ q5 V2 z7 X; X$ g* L8 U
8 U4 i4 K0 J H. \3 d7 @8 a
8 G6 r0 E2 E9 q5 ^, i' \
9 X" w7 ?5 ?1 p6 a% F- @! b1 w g
5 m+ K" {$ ~1 b% Q2 B$ j
8 i3 y! b' D. \
- from itertools import permutations- f6 k# w# A. K\" i) y
- import math
\" K+ o+ p& i; d& x. o - \" K* c+ l. e# a' }3 p5 w+ V* Q
- def tsp_brute(dist):( Y9 }\" G2 K3 ]* X
- """dist: n×n 距离矩阵,返回 (最短长度, 最优回路)"""
H\" ]\" O) o9 ?/ X; U# d( ^8 I - n = len(dist): ~& ?0 \* Z( K. D8 P
- best_len, best_tour = math.inf, None
- @% i9 i( A* |, u - for perm in permutations(range(1, n)): # 固定起点 0
1 }; W( I3 Z, r% }8 i - tour = [0] + list(perm)
2 \6 i: K, x5 T( c7 x- y2 }8 o7 | - L = sum(dist[tour[i]][tour[i+1]] for i in range(n-1)) + dist[tour[-1]][0]
$ A/ j( l0 e5 B# f6 b$ J - if L < best_len:
0 @3 B2 M3 c- Q' h - best_len, best_tour = L, tour; a* e2 [( x9 a% c. z, Q
- return best_len, best_tour
8 [1 z+ x\" J/ _& f& e. r
. e\" z1 A. u6 x, v1 \4 [; ?- # ---------- 2-opt 局部搜索(中大规模) ----------9 H. q8 I& O$ N( w9 X2 k9 k
- def tsp_2opt(dist, max_iter=1000):/ b6 p- T ?( ~+ x0 Q
- n = len(dist); P: v o3 q9 W
- tour = list(range(n)) # 初始:自然顺序
; v& M2 D- {' m - improved = True
- n) F3 m/ T$ F# x0 A+ \ - while improved and max_iter > 0:- E/ {3 k0 a6 E: a! C ^4 P& _
- improved = False
6 [0 I9 ?/ M5 Z - for i in range(1, n-2):, ^+ u: t1 N, Z
- for k in range(i+1, n):
% W @+ X$ X# ^0 m5 E6 `1 | - # 翻转 tour[i:k+1]
7 k- ~& @, n- @ F3 I' c - new_tour = tour[:i] + tour[i:k+1][::-1] + tour[k+1:]
& z% ?4 u$ I; _( r% t - cur = sum(dist[tour[j]][tour[j+1]] for j in range(n-1)) + dist[tour[-1]][tour[0]]& c( e5 h+ B7 Y) G\" G% z: C5 S
- new = sum(dist[new_tour[j]][new_tour[j+1]] for j in range(n-1)) + dist[new_tour[-1]][new_tour[0]]
# B, m- Z! P1 }# K/ R$ I( y - if new < cur:1 y, J- T/ R8 c
- tour, improved = new_tour, True d( ]8 X& n\" g\" J! F
- max_iter -= 1+ g3 G$ e3 h p% f/ U
- L = sum(dist[tour[j]][tour[j+1]] for j in range(n-1)) + dist[tour[-1]][tour[0]]
# l7 z2 [3 j9 _0 j - return L, tour
6 c0 _; g% {/ i5 m+ y - , r Y. h' H4 g. b: x/ o- ?1 g
- # ---------- 测试:4 城市 ----------
& D3 D2 y' i) N - dist = [
8 Y) q4 T/ o) Y% H7 y - [0, 10, 15, 20],
. J3 r& i' t/ C) P3 j% c- B - [10, 0, 35, 25],6 G1 `$ S( ~\" l8 ~. f
- [15, 35, 0, 30],
. P$ w# U5 a5 ~ - [20, 25, 30, 0], c5 B+ Q2 r9 R
- ]
) g( a' k/ t! W2 e* @9 [: `7 E - print("暴力 DFS:", tsp_brute(dist)) # 最短长度 80,回路 0→1→3→2→0& ~3 P! |) i* {9 A1 x3 u1 H' k( X
- print("2-opt :", tsp_2opt(dist))
复制代码 7.2 运行结果- 暴力 DFS: (80, [0, 1, 3, 2])
$ L2 s3 P8 M& y\" X. E1 ]( \ - 2-opt : (95, [0, 1, 2, 3])
复制代码观察:暴力 DFS 保证全局最优( 时可行)。2-opt 从自然顺序出发卡在局部最优 95,未能到达最优解 80——这正是 2-opt 的经典陷阱:单次运行可能陷入局部最优。竞赛中应多次随机重启或结合其他启发式(如先用最近邻初始化再 2-opt)。这也是为什么论文里必须报告"与精确解的 gap",而不是只报一个数字。 8. 竞赛真题映射年份 CUMCM 题目方向 TSP 变体 1 `9 z6 x6 u5 ^: f& a7 J3 Q; }) l
1998B灾情巡视路线巡检 TSP(带时间窗 / 部分覆盖)" l" `% Q5 k6 Y. r2 _
2001C公交车线路设计路径规划 + 容量约束(VRP 变体). A6 Y; D, F7 S+ a( u- s5 i
2008B啤酒运输问题配送路径优化. a9 t5 ]4 x8 g9 _' }5 v1 B
2011A高速公路收费站路网遍历 + 费用优化$ n# k& }( j, W4 G$ z2 @
2015A太阳能小屋设备布点 + 巡检路径
, O, ?2 {3 V4 {' j5 N2 e+ K" ]2017B煤炭产量预测无关(数据题)
' J3 d5 R- m6 q2 J2020A炉温曲线无关(拟合题)3 R+ H( ^1 D. i
近年物流配送 / 应急巡检 / 传感器网络TSP / VRP / 覆盖路径核心规律:只要赛题出现"一条路走遍多个地点",TSP 或其变体(VRP、TSP with Time Windows、多车 TSP)就是最自然的建模原型。先用 TSP 建原型,再根据约束升级为 VRP,是数模竞赛的成熟套路。 9. 常见误区与赛场自查# 误区 正解
4 }- x- s' j: \" w5 x5 P1"TSP 可以用贪心算法精确求解"贪心(最近邻)不保证最优,存在反例3 m) N+ ]( C4 y" }" _
2"2-opt 一定得到全局最优"2-opt 是局部搜索,可能陷入局部最优
0 `* [5 w4 T8 C- m3"TSP 和指派问题等价"TSP 要求单一回路,指派问题允许子回路3 m1 M7 Q0 {+ n3 m9 _
4"子回路消除约束可以一次性写完"数量 级别,实际用逐步加入(lazy constraint)
+ w% f; P) l2 A$ s) X% I5"DP 复杂度 "准确是 ,每状态需 转移
+ T( W! M3 w) X1 b# t6"所有 TSP 都有常数近似比"仅度量 TSP(三角不等式)有 Christofides 近似
% i9 I, G: o# B% e5 V7"对称 TSP 和非对称 TSP 一样"对称: 种回路;非对称: 种赛场自查清单: - 我确认了距离矩阵是否对称、是否满足三角不等式(影响算法选择)。
- 我估计了可行解数量 ,判断暴力 / B&B / 启发式的适用性。
- 若用 B&B:下界函数是否安全(不高于最优值)且紧?
- 若用 2-opt:是否报告了与精确解的偏差(小规模对比)?
- 若用 Christofides:是否验证了三角不等式成立?
- 论文中是否报告了运行时间与最优性差距(gap)?
- 是否对结果做了敏感性分析(距离矩阵微调时回路是否稳定)?
- 是否给出了子回路消除的处理方式(lazy constraint 或逐步加入)?
1 q5 f9 m+ G' N$ {
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,这是评委最认可的"务实"策略。记住:能证明最优的解,比看似漂亮但无保证的解更有说服力。
0 c' J$ u* M/ n
/ z% j& Q6 w" V0 o8 V |