NeFut Logo NeFut
EN 管理员登录

状态压缩动态规划:旅行商问题的高效求解

发布于:2026-05-27 09:17 最后更新:2026-06-06 13:04
#algorithm #Dynamic Programming #DP

核心逻辑与数学原理

状态压缩动态规划(State Compression DP,简称状压 DP)的核心本质是将一维具有强离散特征的组合集合,通过数制转换(通常为二进制)无损映射为一个低维的整数标量。这种降维映射能够让我们在 $O(1)$ 的时间内通过位运算进行状态的物理转移与冲突校验。

旅行商问题(TSP, Travelling Salesman Problem)是状压 DP 的教科书级模型:给定一个图及两两节点之间的距离,求一条经过所有顶点恰好一次且总权值最小的回路(本节讨论其变型:求从起点 0 触发,经过所有顶点恰好一次到达终点 $N-1$ 的最小权值路径)。

1. 状态空间的离散映射

在 TSP 问题中,我们不仅需要知道当前身处哪一个城市,更需要知道已经访问过了哪些城市,还剩下哪些城市没有访问

2. 位运算控制矩阵与状态转移的算子化

借助计算机底层的位运算,集合的交、并、补、属于等操作可以高度抽象为以下算子:

集合操作 位运算数学表达式 物理语义
判定属于 (S >> i) & 1 检查城市 $i$ 是否已被访问(是否为 1)
集合并入 S | (1 << i) 将城市 $i$ 强行标记为已被访问
集合消除 S & ~(1 << i) 将城市 $i$ 从已访问集合中剔除
全集表达 (1 << N) - 1 得到一个包含 $N$ 个 1 的全选状态

状态设计与算法推导

1. 状态空间定义

设状态 $f[S][i]$ 表示:当前已经访问的城市集合为 $S$(其二进制掩码对应的十进制整数),且当前正站在城市 $i$ 上时,所花费的最小总距离。

2. 状态转移方程推导

我们通过逆向寻找当前状态的前驱来实施决策。在当前身处城市 $i$、集合为 $S$ 之前,上一步我们一定身处另一个不同的城市 $j$。
由于从 $j$ 跨步到了 $i$,那么在上一步时,城市 $i$ 一定处于未访问的状态。因此,前驱状态的城市集合必然是 $S - \{i\}$,在位运算中表达为 S ^ (1 << i)

$$\forall j \in S \setminus \{i\}, \quad f[S][i] = \min \left( f[S][i], f[S \setminus \{i\}][j] + \text{weight}(j, i) \right)$$

代入位运算算子:

f[S][i] = min(f[S][i], f[S ^ (1 << i)][j] + weight[j][i]);

3. 拓扑序的控制控制

由于大集合的状态总是由小集合(少一个元素的集合)状态推导而来,在底层的双重循环中,外层循环必须严格从小到大枚举状态数 $S$(从 1 到 $(1<


NOIP 实战避坑指南

1. 位运算优先级混乱导致逻辑瘫痪

2. 空间维度开辟错误引发内存爆表(MLE)


经典 NOIP/洛谷 真题

1. 洛谷 P1433 吃奶酪

2. 洛谷 P1879 [USACO06NOV] Corn Fields G

原文链接: local://17.1

[h] 返回首页