题目描述
物流公司要把一批货物从码头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; }