题目大意: 维克多现在在一个数字是1的国家,他想知道他访问每个国家至少一次并最终返回第一个国家的最低燃料量。
解题思路: 我是初学状压dp看视频的时候知道了这题,在视频中其实已经差不多把这题差不多讲明白了,首先用二进制数表示城市的状态,如果上一个城市是已经走过的状态,这个城市才能由上一个状态转移过来,唯一要注意的就是最短路了,挺久没写最短路,都有点忘了。
代码:
#include<bits/stdc++.h>
#define pb emplace_back
// #define LOCAL
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+5;
typedef long long ll;
typedef pair<int,int> Pii;
template <typename T>inline void read(T& t){
char c=getchar();t=0;
int f=1;
while(!isdigit(c)){
if(c=='-')f=-1;
c=getchar();
}
while(isdigit(c))t=t*10+c-48,c=getchar();
t=f*t;
}
template <typename T,typename... Args> inline void read(T& t,Args&... args){
read(t);read(args...);
}
int n,m;
int mps[20][20];
int main(){
// #ifdef LOCAL
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// #endif
int t;
read(t);
while(t--){
read(n,m);
memset(mps,inf,sizeof(mps));//初始化
for(int i=1;i<=m;i++){
int u,v,w;
read(u,v,w);
--u,--v;
mps[u][v]=mps[v][u]=min(mps[u][v],w);
}
for(int i=0;i<n;i++)mps[i][i]=0;
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(mps[i][j]>mps[i][k]+mps[k][j]){
}
mps[i][j]=min(mps[i][j],mps[i][k]+mps[k][j]);
}
}
}
vector<vector<int>>dp(n,vector<int>(1<<n,inf));//开二维数组,初始化为inf
dp[0][1]=0;
for(int s=0;s<(1<<n);s++){
for(int i=0;i<n;i++){
if(s&(1<<i)){
for(int j=0;j<n;j++){
if(!(s&(1<<j))&&mps[i][j]){
dp[j][s|(1<<j)]=min(dp[j][s|(1<<j)],dp[i][s]+mps[i][j]);
}
}
}
}
}
int ans=inf;
for(int i=0;i<n;i++){
ans=min(ans,dp[i][(1<<n)-1]+mps[i][0]);
}
printf("%d\n",ans);
}
return 0;
}