题目描述
物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是—件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。
我们令f[i]表示到第i天所需要的花费,我们假设第j天到第i天的线路一样,第j天和第j-1天不一样那么我们能得出方程:
f[i]=min(f[i],f[j]+(i-j+1)*cost+K)
cost用Dijkstra求就可以了,但是注意,要标记未开通的边不能走。
#include <iostream> #include <cstdio> #include <cstdlib> #include <queue> #include <cstring> #define in(a) a=read() #define REP(i,k,n) for(int i=k;i<=n;i++) #define MAXN 2005 using namespace std; inline int read(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } //queue <int> Q; typedef pair<int,int> P; int n,m,K,e,d; int total,head[MAXN],to[MAXN<<1],nxt[MAXN<<1],val[MAXN<<1]; int f[MAXN],book[MAXN][MAXN],ban[MAXN],dis[MAXN],vis[MAXN]; priority_queue<P, vector<P>,greater<P> > Q; inline void adl(int a,int b,int c){ total++; to[total]=b; val[total]=c; nxt[total]=head[a]; head[a]=total; return ; } inline int Dijkstra(){ memset(dis,127,sizeof(dis)); dis[1]=0; Q.push(P(0,1)); while(!Q.empty()){ int u=Q.top().second;Q.pop(); if(vis[u]) continue; vis[u]=0; for(int e=head[u];e;e=nxt[e]) if(dis[to[e]]>dis[u]+val[e] && !ban[to[e]]){ dis[to[e]]=dis[u]+val[e]; Q.push(P(dis[to[e]],to[e])); } } return dis[m]; } int main(){ int a,b,c; in(n),in(m),in(K),in(e); REP(i,1,e) in(a),in(b),in(c),adl(a,b,c),adl(b,a,c); in(d); REP(i,1,d){ in(a),in(b),in(c); REP(j,b,c) book[a][j]=1; } memset(f,127,sizeof(f)); f[0]=-K; REP(i,1,n){ REP(j,1,m) ban[j]=0; for(int j=i;j>=1;j--){ REP(k,1,m) if(book[k][j]) ban[k]=1; int sum=Dijkstra(); if(sum>=100000000) break; f[i]=min(f[i],f[j-1]+(i-j+1)*sum+K); } } cout<<f[n]; return 0; }