• Travelling(TSP、状态压缩) 题解


    Acmer先生决定访问n座城市。他可以空降到任意城市,然后开始访问,要求访问到所有城市,任何一个城市访问的次数不少于1次,不多于2次。n座城市间有m条道路,每条道路都有路费,求Acmer先生完成旅行所需要花费的最小费用。

    第一行是n,m,后面有m行,有3个整数a,b,c,表示城市a和b之间的路费是c

    输出最少花费,如果不能完成旅行,则输出-1;

    这里考察的是三进制状态压缩dp

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    int n,m;
    int bit[12]={0,1,3,9,27,81,243,729,2187,6561,19683,59049};//三进制每一位的权值 
    int tri[60000][11];
    int dp[11][60000];
    int graph[11][11];//存图 
    void make_trb(){       //初始化,求所有可能的路径 
        for(int i=0;i<59050;++i)  //共3的10次方=59050因为题目要求1=<n<=10 
        {
            int t=i;
            for(int j=1;j<=10;++j){
                tri[i][j]=t%3;t/=3;
            }
        }
        }
        int comp_dp(){
            int ans=inf;
            memset(dp,inf,sizeof(dp));
            for(int i=0;i<=n;i++)
            dp[i][bit[i]]=0;    //bit[i]是第i个城市,起点是任意的 
            for(int i=0;i<bit[n+1];i++){
                int flag=1;             //所有的城市都遍历过一次以上 
                for(int j=1;j<=n;j++)     //选一个终点 
                {
                    if(tri[i][j]==0)       //判断终点位是不是0 
                    {
                        flag=0;             //还没有经过所有点 
                        continue;
                    }
                    if(i==j) continue;
                    for(int k=1;k<=n;k++)
                    {
                        int l=i-bit[j];     //i状态的第j位置0 
                        if( tri[i][k]==0)  continue;
                        dp[j][i]=min(dp[j][i],dp[k][l]+graph[k][j]);
                    }
                }
                if(flag)                     //找最少费用 
                for(int j=1;j<=n;j++)
                ans=min(ans,dp[j][i]); 
            }
            return ans;
        }
        int main()
        {
            std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);//打消iostream的输入和输出缓存,节省时间
            make_trb();
            while(cin>>n>>m){
                memset(graph,inf,sizeof(graph));
                while(m--){
                    int a,b,c;
                    cin>>a>>b>>c;
                    if(c<graph[a][b])
                    graph[a][b]=graph[b][a]=c;
                } 
                int ans=comp_dp();
                if(ans==inf) 
                cout<<"-1"<<endl;
                else 
                cout<<ans<<endl;
            } 
        }
  • 相关阅读:
    bootstap 折叠
    AtCoder AGC019E Shuffle and Swap (DP、FFT、多项式求逆、多项式快速幂)
    Codeforces Gym 101630J Journey from Petersburg to Moscow (最短路)
    BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)
    BZOJ 2734 [HNOI2012]集合选数 (状压DP、时间复杂度分析)
    BZOJ 2759 一个动态树好题 (LCT)
    Codeforces 1205C Palindromic Paths (交互题、DP)
    getopt实现传参自动识别
    powershell笔记
    bat语法需要注意的地方
  • 原文地址:https://www.cnblogs.com/hrlsm/p/12798616.html
Copyright © 2020-2023  润新知