每日一题——最短Hamilton路径
题目
题解
这里的数据范围n为20,若暴力强行解的话时间肯定是不够的,所以我们要考虑如何知道哪些边走过,可以使用状态压缩的思想,而且我们要的不是所有解法而是最优解,所以只需要存储min即可,f[i][j]中的i表示当前状态,比如有1、2、3、4四个点,1100就表示1、2两个点走过,1011就表示1、3、4三个点走过,j表示的是当前走到的终点,现在既然已经确定好了当前终点j,那么这个j点是由哪一个状态移动而来的呢?我们可以选择k,也就是说我们的状态转移方程可以为
f[i][j] = min(f[i][j], f[i - (1 << j) ][k] + weight[k][j])
参考代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 20, M = 1 << N;
int n;
int f[M][N],w[N][N];
int main(){
cin >> n;
memset(f, 0x3f, sizeof f);
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
cin >> w[i][j];
}
}
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] = min(f[i][j], f[i-(1 << j)][k] + w[k][j]);
}
}
}
}
cout << f[(1 << n) -1][n - 1] << endl;
return 0;
}

浙公网安备 33010602011771号