旅行商问题(动态规划解法)
字数 1074 2025-11-13 05:30:33
旅行商问题(动态规划解法)
题目描述:
给定一系列城市和每对城市之间的距离,旅行商问题要求找到一条最短的可能路径,使得旅行商访问每个城市恰好一次,并最终返回起点城市。这是一个经典的NP-hard问题,在组合优化和图论中具有重要地位。
解题过程:
1. 问题建模
- 将城市表示为带权完全图G=(V,E)的顶点,其中|V|=n
- 边权重d(i,j)表示城市i到城市j的距离
- 目标是找到访问所有顶点恰好一次的最短哈密顿回路
2. 动态规划状态设计
定义状态dp[mask][i]:
- mask:二进制位掩码,表示已访问的城市集合(1表示已访问,0表示未访问)
- i:当前所在的城市编号
- dp[mask][i]:从城市0出发,经过mask表示的城市集合,最后到达城市i的最短路径长度
3. 状态转移方程
对于每个状态dp[mask][i],考虑所有可能的前一个城市j:
dp[mask][i] = min{ dp[mask⊕(1<<i)][j] + d(j,i) }
其中:
- j ∈ mask且j ≠ i
- mask⊕(1<<i)表示从mask中移除城市i
- d(j,i)是城市j到城市i的距离
4. 初始化
- dp[1][0] = 0 (只访问了城市0,且当前在城市0,路径长度为0)
- 其他状态初始化为无穷大
5. 算法步骤
步骤1:预处理距离矩阵
- 创建n×n的矩阵dist,存储每对城市间的距离
步骤2:初始化DP表
- 创建大小为2^n × n的DP数组
- 设置dp[1][0] = 0,其他为∞
步骤3:状态转移
for mask从1到(1<<n)-1:
for i从0到n-1:
if mask的第i位为1: # 城市i在已访问集合中
for j从0到n-1:
if mask的第j位为1且j ≠ i:
new_mask = mask XOR (1 << i)
dp[mask][i] = min(dp[mask][i],
dp[new_mask][j] + dist[j][i])
步骤4:计算最终结果
- 最终需要返回起点城市0
- 结果 = min{ dp[(1<<n)-1][i] + dist[i][0] },对所有的i从1到n-1
6. 复杂度分析
- 时间复杂度:O(n² × 2^n)
- 空间复杂度:O(n × 2^n)
- 适用于n ≤ 20左右的中等规模问题
7. 实例演示
考虑4个城市的情况:
城市:0, 1, 2, 3
距离矩阵:
0 10 15 20
10 0 35 25
15 35 0 30
20 25 30 0
计算过程:
- 初始化:dp[0001][0] = 0
- 逐步计算包含更多城市的状态
- 最终:dp[1111][1] + dist[1][0] = 80
dp[1111][2] + dist[2][0] = 95
dp[1111][3] + dist[3][0] = 80 - 最优解:80(路径0→1→3→2→0)
这种方法通过动态规划避免了暴力枚举所有n!种排列,在中等规模问题上提供了可行的解决方案。