每日一题——最短Hamilton路径

题目

最短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;
}
posted @ 2025-03-04 16:14  PZnwbh  阅读(5)  评论(0)    收藏  举报