题意
给出一张
n
(
n
≤
20
)
n(n \leq 20)
n(n≤20)个点的带权无向图,求出起点0到终点n-1的最短Hamilton路径。
Hamilton路径的定义是从0到n-1不重不漏的经过每个点恰好一次。
思路
二进制压缩每个点走过的情况,进行转移。
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为当前状态为
i
i
i,停在点
j
j
j的最短路径,可以得出转移方程:
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
f
[
i
x
o
r
1
<
<
j
]
[
k
]
+
w
[
k
]
[
j
]
)
f[i][j]=min(f[i][j],f[i\ xor\ 1<<j][k]+w[k][j])
f[i][j]=min(f[i][j],f[i xor 1<<j][k]+w[k][j]),其中i>>j&1>0; i>>k&1>0。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
int n;
int f[1 << 20][20], edge[20][20];
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &edge[i][j]);
memset(f, 127 / 3, sizeof(f));
f[1][0] = 0;
for (int i = 1; i < 1 << n; i++)
for (int j = 0; j < n; j++) if (i >> j & 1)
for (int k = 0; k < n; k++) if (i >> k & 1)
f[i][j] = std::min(f[i][j], f[i ^ 1 << j][k] + edge[k][j]);
printf("%d", f[(1 << n) - 1][n - 1]);
}