题目链接: 91. 最短Hamilton路径 - AcWing题库
题意: 给定一张n(n<=20)个点的带权无向图,点从0~n-1标号,求起点0到终点n-1的最短Hamilton路径。Hamilton路径的定义是从0~n-1不重不漏地经过每个点恰好一次。
分析: 二进制状态压缩, 把每个点是否经过用一个二进制位标记,然后做dp。f[i][j]代表经过的点的状态对应的十进制数为i,这时经过的最后一个点为j, 那么第一维枚举从1到(1<<n)的所有状态,第二维枚举终点,第三维枚举中间状态。
代码:
#include<bits/stdc++.h>
#define map unordered_map
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
int n;
int mp[25][25];
int f[1 << 20][20];
void solve(){
cin>>n;
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
cin>>mp[i][j];
}
}
memset(f, 0x3f, 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){ // j点已经走过
for(int k = 0; k < n; k ++){
if((i ^ 1 << j) >> k & 1){ // 还没走j点,但是已经走到了k点
f[i][j] = min(f[i][j], f[i ^ 1 << j][k] + mp[k][j]);
}
}
}
}
}
cout<<f[(1 << n) - 1][n - 1]<<endl;
}
int main(){
cin.tie(0) -> sync_with_stdio(false);
//int t; cin>>t; while(t --)
solve();
}