zoukankan      html  css  js  c++  java
  • 2020牛客国庆集训派对day2 B【Cheap Delivers】(最短路+状压dp)

    题目链接:https://ac.nowcoder.com/acm/contest/7818/B

    题意:给你n个点,m条边(n,m<=1e4),k个任务(k<=18)。每次你只能执行一个任务(任务即从u点走到v点),问以最优走法完成所有任务的最短距离是多少。

    题解:首先对于每个单独的任务而言,其u到v必定是走他们的最短路。所以ans1为所有任务(u->v)的最短路之和,这是不可避免的。接下来就要考虑优化合理分配任务的执行顺序了。当前的终点走到下一个点的起点取决于我们的选取方案。因为k的范围(k<=18)比较小,所以考虑用状态压缩dp枚举所有方案,优化到最新最优。

    其中 dist[i][j] 表示从i的终点走到j点的起点所花费的距离,那么你对于每次任务都可以直接通过dijstra算法求出。

    其中 dp[i][j] 表示当前状态是i,然后你目前位于j点的花费情况。先初始化dp为inf。那么显而易见的就是对于第i个任务而言,dp[1<<i][i] = dist[i][i]。

    那么接下来就是状态转移了:

     最后就是对于结果的输出了:

    AC代码:

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define white 0
    #define black 1
    #define grey  2
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e4+5;
    int tot,head[maxn];
    struct E{
        int to,next,w;
    }edge[maxn<<1];
    void add(int u,int v,int w){
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m,k;
    ll d[maxn];ll color[maxn];
    priority_queue<pair<ll,ll> >q; 
    void Dijkstra(ll s){
        for(ll i=0;i<=n;i++) d[i]=inf,color[i]=white;
        d[s]=0;
        q.push(make_pair(0,s));
        color[s]=grey;
        while(!q.empty()){
            pair<ll,ll> f=q.top();
            q.pop();
            ll u=f.second;
            color[u]=black;
            if(d[u]<f.first*(-1)) continue;
            for(ll i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if(color[v]==black) continue;
                if(d[v]>d[u]+edge[i].w){
                    d[v]=d[u]+edge[i].w;
                    q.push(make_pair(d[v]*(-1),v));
                    color[v]=grey;
                }        
            }
        }
    }
    
    ll dist[20][20],dp[1<<18][18];
    int st[20],ed[20];
    int main(){
        scanf("%d%d%d",&n,&m,&k);mem(head,-1);
        for(int i=0;i<m;i++){
            int u,v,w;scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        for(int i=0;i<k;i++){
            scanf("%d%d",&st[i],&ed[i]);
        }
        for(int i=0;i<k;i++){
            Dijkstra(ed[i]);
            for(int j=0;j<k;j++){
                dist[i][j]=d[st[j]];
            }
        }
        for(int i=0;i<(1<<k);i++){
            for(int j=0;j<k;j++){
                dp[i][j]=inf;
            }
        }
        for(int i=0;i<k;i++){
            dp[1<<i][i]=dist[i][i];
        }
        for(int i=0;i<(1<<k);i++){
            for(int j=0;j<k;j++){
                if(i&(1<<j)){
                    for(int p=0;p<k;p++){
                        if(i&(1<<p)) continue;
                        dp[i|(1<<p)][p]=min(dp[i|(1<<p)][p],dp[i][j]+dist[j][p]+dist[p][p]);
                    }
                }
            }
        }
        ll ans=inf;
        for(int i=0;i<k;i++){
            ans=min(ans,dp[(1<<k)-1][i]);
        }
        if(ans>=inf) cout<<-1<<endl;
        else cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    压缩命令
    常用命令7-帮助命令1
    常用命令6--文件搜索命令4-grep
    常用命令5--文件搜索命令3-find
    常用命令4-文件搜索命令 2- which
    【转】Castle开发系列文章
    【摘录】C#多线程编程
    优化一
    Value Shadowing(不明確的方式存取变量)
    portability flaw : file separator (可移植性缺陷:文件分隔符)
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13767026.html
Copyright © 2011-2022 走看看