hdu5418--Victor and World(最短路径+状压dp)

题目链接


题目大意: 维克多现在在一个数字是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值