zoukankan      html  css  js  c++  java
  • 2020牛客国庆集训派对day2

    Description

    (n le 10^4) 个点 (m le 10^4) 条边的无向图上,有 (k le 18) 个运输任务,每个任务从 (F_i)(D_i)。你只能同时处理一个任务。你可以从任何一点开始到任何一点结束。求运输所有任务的行走距离的最小值。

    Solution

    (f[i][S]) 表示最后一次运完第 (i) 个任务并停在 (D_i) 处,已经完成的运输任务的集合为 (S),此时的最小距离为多少。Dijkstra 或 SPFA 预处理后状压 DP 即可。

    考场上这个题 WA 了无数发,最后发现数初始值设置小了——谨慎使用 memset 进行初始值设定……

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 10005;
    const int M = 25;
    const int U = 600000;
    
    #define reset(x) memset(x,0,sizeof x)
    #define reset3f(x) memset(x,0x3f,sizeof x)
    
    // 参数:点数n  源点v0
    // 方法:make建边  reset_graph清图  solve计算
    // 输出:d最短路数组
    namespace sp {
    vector<pair<int,int> > g[N];
    int n,v0=1,d[N],v[N];
    void make(int t1,int t2,int t3) {
        g[t1].push_back(make_pair(t2,t3));
        g[t2].push_back(make_pair(t1,t3));
    }
    void reset_graph() {
        for(int i=0;i<=n;i++) g[i].clear();
    }
    void solve(int _v0) {
        v0=_v0;
        queue <int> qu;
        for(int i=1;i<=n;i++) v[i]=0, d[i]=1e18;
        d[v0]=0; v[v0]=1; qu.push(v0);
        while(qu.size()) {
            int p=qu.front();
            qu.pop();
            v[p]=0;
            for(int i=0;i<g[p].size();i++) {
                int q=g[p][i].first,w=g[p][i].second;
                if(d[q]>d[p]+w) {
                    d[q]=d[p]+w;
                    if(!v[q]) qu.push(q), v[q]=1;
                }
            }
        }
    }
    }
    
    int dist[M][M];
    
    int n,m,k,t1,t2,t3,f[N],d[N],dp[M][U];
    
    signed main()
    {
        cin>>n>>m>>k;
        sp::n=n;
        for(int i=1;i<=m;i++)
        {
            cin>>t1>>t2>>t3;
            sp::make(t1,t2,t3);
        }
        for(int i=1;i<=k;i++)
        {
            cin>>f[i]>>d[i];
        }
        for(int i=1;i<=k;i++)
        {
            sp::solve(d[i]);
            for(int j=1;j<=k;j++)
            {
                dist[i][j]=sp::d[f[j]];
            }
        }
        for(int i=1;i<=k;i++)
        {
            for(int j=0;j<(1<<k);j++)
            {
                dp[i][j]=1e18;
            }
        }
        for(int i=1;i<=k;i++)
        {
            dp[i][1<<(i-1)]=dist[i][i];
        }
    
        for(int s=1;s<(1<<k);s++)
        {
            for(int i=1;i<=k;i++) if(s&(1<<(i-1)))
            {
                for(int j=1;j<=k;j++)
                {
                    if(s&(1<<(j-1))) continue;
                    dp[j][s|(1<<(j-1))]=min(dp[j][s|(1<<(j-1))],dp[i][s]+dist[i][j]+dist[j][j]);
                }
            }
        }
    
        int ans=1e18;
        for(int i=1;i<=k;i++)
        {
            ans=min(ans,dp[i][(1<<k)-1]);
        }
        if(ans>1e17)
        {
            cout<<-1<<endl;
        }
        else
        {
            cout<<ans<<endl;
        }
        
        return 0;
    }
    
    
  • 相关阅读:
    Cocos2d-x 内存管理
    Cocos2d-x 解惑
    前端最实用、全面的工具类方法
    Java web 项目获取时间的方式列举
    Win系统常用指令
    Js三级下拉列表联动
    Js数组操作
    常用网站推荐
    最常用的正则表达式
    Oracle数据库学习
  • 原文地址:https://www.cnblogs.com/mollnn/p/13797188.html
Copyright © 2011-2022 走看看