1)题目意思
有 n 个村庄(编号 1 到 n),村庄之间是有向路,从 i 到 j 的距离是 s[i][j],一般 s[i][j] 不等于 s[j][i]。
售货员从村庄 1(商店在 1)出发,要把 每个村庄恰好去一次,最后再回到村庄 1。
问最短总路程是多少,输出这个最小值。
2 <= n <= 20。
这就是经典的 TSP(旅行商)有向版。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2)思路解析(状态压缩 DP)
因为 n<=20,可以用二进制 mask 表示已经访问过哪些村庄。
* mask 的第 i 位为 1 表示村庄 i 已访问(这里用 0..n-1 表示村庄 1..n)
* 必须从村庄 0(也就是 1 号村)出发
状态定义
dp[mask][i] 表示:
* 从村庄 0 出发
* 访问过的集合为 mask(一定包含村庄 0)
* 当前停在村庄 i
的最短路程。
初始化
* dp[1<<0][0] = 0,表示只在起点
转移
从 dp[mask][i] 走到一个没访问过的 j:
* dp[mask | (1<<j)][j] = min(dp[mask | (1<<j)][j], dp[mask][i] + s[i][j])
答案
当所有村庄都访问完 FULL=(1<<n)-1,最后要回到 0:
* ans = min(dp[FULL][i] + s[i][0])
复杂度
* 状态数约 2^n * n
* 转移约 2^n * n^2
n=20 可以通过。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3)代码