思路:
- 类似于 算法竞赛进阶指南 中的例题 最短Hamilton路径 ,只是多了一个”跳跃“的属性
- 对于原例题,我们采取 状压dp 的思路来求得以每一个状态结束时的最优解
- 有两维:当前选取值(二进制串)、当前所在位置
- 对于本题,我们考虑分层图的思路(记录一个类似的状态)也就是记录当前跳跃了几次。
#include <bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long typedef pair<int, int> pii; typedef pair<int, char> pic; const int N = 16; const int mod = 1e9 + 7; int n, a[N][N]; int dp[1 << N][N][3]; int main() { cin >> n; for(int i = 0; i < n; i ++) for(int j = 0; j < n; j ++) cin >> a[i][j]; memset(dp, 0x3f, sizeof(dp)); for(int i = 0; i < n; i ++) dp[1 << i][i][0] = 0; for(int i = 1; i < (1 << n); i ++) { for(int j = 0; (1 << j) <= i; j ++) { if(((1 << j) & i) == 0) continue; int x = (1 << j) ^ i; for(int k = 0; (1 << k) <= x; k ++) { if(((1 << k) & x) == 0) continue; dp[i][j][0] = min(dp[i][j][0], dp[x][k][0] + a[k][j]); dp[i][j][1] = min(dp[i][j][1], min(dp[x][k][0], dp[x][k][1] + a[k][j])); dp[i][j][2] = min(dp[i][j][2], min(dp[x][k][2] + a[k][j], dp[x][k][1] + 2 * a[k][j])); } } } int ans = 0x3fffffff; for(int i = 0; i < n; i ++) ans = min(ans, dp[(1 << n) - 1][i][2]); cout << ans; return 0; }