• [ZJOI2006]物流运输


    题目描述

    物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是—件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。

    做法dp+最短路。找出 l 到 r 这些天都可走的最短路,然后dp一下。

    代码:

    #include<queue>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 105
    #define M 25
    #define inf 999999999999999ll
    typedef long long ll;
    ll n,m,K,E,hed[N],cnt;
    struct EG
    {
        ll to,nxt,val;
    }e[M*M];
    void ae(ll f,ll t,ll v)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].val = v;
        hed[f] = cnt;
    }
    ll dp[N];
    ll vis[M],vs[N][M],f[N][N];
    struct node
    {
        ll x;
        ll dis;
        node(){}
        node(ll x,ll dis):x(x),dis(dis){}
        friend bool operator < (node a,node b)
        {
            return a.dis>b.dis;
        }
    };
    ll ds[M];
    bool use[M];
    ll dij()
    {
        priority_queue<node>q;
        q.push(node(1,0));
        use[1]=0;
        for(ll i = 2;i<=m;i++)ds[i]=inf,use[i]=0;
        ll ret = inf;
        while(!q.empty())
        {
            node tp = q.top();
            q.pop();
            ll x = tp.x;
            if(use[x])continue;
            use[x]=1;
            if(ds[x]>ret)break;
            for(ll j=hed[x];j;j=e[j].nxt)
            {
                ll to = e[j].to;
                if(vis[to])continue;
                ll ds1 = ds[x]+e[j].val;
                if(ds[to]>ds1)
                {
                    ds[to]=ds1;
                    if(to==m)ret = ret<ds1?ret:ds1;
                    else q.push(node(to,ds1));
                }
            }
        }
        return ret;
    }
    int main()
    {
        scanf("%lld%lld%lld%lld",&n,&m,&K,&E);
        for(ll ff,t,v,i=1;i<=E;i++)
        {
            scanf("%lld%lld%lld",&ff,&t,&v);
            ae(ff,t,v);
            ae(t,ff,v);
        }
        ll d;
        scanf("%lld",&d);
        for(ll p,a,b,i=1;i<=d;i++)
        {
            scanf("%lld%lld%lld",&p,&a,&b);
            for(ll j=a;j<=b;j++)
            {
                vs[j][p]=1;
            }
        }
        dp[0]=-K;
        for(ll i=1;i<=n;i++)dp[i]=inf;
        for(ll i=1;i<=n;i++)
        {
            for(ll j=i;j<=n;j++)
            {
                for(ll k=1;k<=m;k++)vis[k]|=vs[j][k];
                if(f[i][j-1]==inf)f[i][j]=inf;
                else f[i][j] = dij();
                if(f[i][j]==inf)continue;
                dp[j]=min(dp[j],dp[i-1]+K+f[i][j]*(j-i+1));
            }
            for(ll k=1;k<=m;k++)
                vis[k]=0;
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }
  • 相关阅读:
    centos golang 环境配置
    运行安全审计 npm audit
    Oracle ——UTL_SMTP包发送Email
    UML学习入门就这一篇文章
    UML ——类图和对象图
    SQL SERVER 行列转换(转自别人)
    Oracle行列转换小结
    同步调用/异步调用(摘自百度)
    C#中Invoke的用法(Winform编程)
    udpclient之异步编程
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9657330.html
Copyright © 2020-2023  润新知