解题思路(状态压缩 TSP)
要求从城市 1 出发,至少经过所有城市一次并回到城市 1 的最小花费。因为花费都是非负的,重复走路只会更大,所以最优解一定可以看作:每个城市恰好访问一次(最后回到 1),也就是 TSP 问题。
N ≤ 17,可以用 状态压缩 DP。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1)预处理两两移动代价
城市 i 到城市 j 的花费:
* abs(Xj - Xi) + abs(Yj - Yi) + max(0, Zj - Zi)
先把 cost[i][j] 预处理出来,后面 DP 直接查表。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2)DP 定义
用二进制 mask 表示已经访问过的城市集合(包含城市 0 代表城市 1)。
定义:
* dp[mask][i]:从城市 1 出发,访问了 mask 里的所有城市,并且当前停在 i 的最小花费
这里 i 用 0..N-1 表示城市 1..N。
初始化:
* dp[1<<0][0] = 0(只在城市 1)
转移:
* 从 dp[mask][i] 走到一个没访问过的 j:
* dp[mask | (1<<j)][j] = min(dp[mask | (1<<j)][j], dp[mask][i] + cost[i][j])
答案:
* 最后要回到城市 1:
* ans = min(dp[full][i] + cost[i][0]),其中 full = (1<<N) - 1
复杂度大约 O(N^2 * 2^N),N=17 可以通过。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C++ 代码