n 很小,所以考虑状压。
设 fi,S 表示最后停在 i 这个点,经过的点集合为 S 的最短路径长度。
初始状态 f0,1=0,答案 fn−1,2n−1。
考虑转移,枚举 S,i,再枚举上一次从 k 过来。时间复杂度 O(2n×n2),由于时限 5s,可以通过。
#include <bits/stdc++.h>
using namespace std;
const int N = 25, M = (1 << 20) + 15;
int n, w[N][N];
int dp[N][M];
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) scanf("%d", &w[i][j]);
memset(dp, 0x3f3f3f3f, sizeof dp);
dp[0][1] = 0; //起点是 0
for (int S = 0; S < (1 << n); S++) {
for (int i = 0; i < n; i++) {
if ((S & (1 << i)) == 0) continue;
for (int j = 0; j < n; j++) {
int S2 = (S ^ (1 << i));
if (S2 & (1 << j))
dp[i][S] = min(dp[i][S], dp[j][S2] + w[i][j]);
}
}
}
printf("%d\n", dp[n - 1][(1 << n) - 1]);
return 0;
}