首页 > 代码库 > [ZJOI2006]物流运输

[ZJOI2006]物流运输

题目描述

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

输入输出格式

输入格式:

 

第一行是四个整数n(l≤n≤100)、m(l≤m≤20)、K和e。n表示货物运输所需天数,m表示码头总数,K表示每次修改运输路线所需成本。接下来e行每行是一条航线描述,包括了三个整数,依次表示航线连接的两个码头编号以及航线长度(>0)。其中码头A编号为1,码头B编号为m。单位长度的运输费用为1。航线是双向的。再接下来一行是一个整数d,后面的d行每行是三个整数P(1<P<m),a,b(1≤a≤b≤n)。表示编号为P的码头从第a天到第b天无法装卸货物(含头尾)。同一个码头有可能在多个时间段内不可用。但任何时间都存在至少一条从码头A到码头B的运输路线。

 

输出格式:

 

包括了一个整数表示最小的总成本。总成本=n天运输路线长度之和+K*改变运输路线的次数。

 

输入输出样例

输入样例#1:
  5 5 10 8
  1 2 1
  1 3 3
  1 4 2
  2 3 2
  2 4 4
  3 4 1
  3 5 2
  4 5 2
  4
  2 2 3
  3 1 1
  3 3 3
  4 4 5
输出样例#1:
32

说明

【样例输入说明】

技术分享

上图依次表示第1至第5天的情况,阴影表示不可用的码头。

【样例输出说明】

前三天走1-4-5,后两天走1-3-5,这样总成本为(2+2)*3+(3+2)*2+10=32。

_NOI导刊2010提高(01)

最短路+dp

预处理每天的最短路,再dp选择。

可以用f[i]表示到第i天的时候最小费用,那么f[i]={f[j]+cost[j+1,i]+K}(0<=j<i),其中cost[i,j]表示由第i天到第j天都可以走得通的最短路。

对于一个点在i~j是否开通可以用前缀和,一个点l~r关闭就赋值1,求出前缀和

判断时sum[x][j]-sum[x][i-1]=0就可以

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 struct Node
 7 {
 8     int next,to;
 9     long long dis;
10 }edge[200001];
11 long long dist[10001];
12 int vis[10001],head[100001],q[100001],b[1001][1001];
13 int n,m,k,e,d,num;
14 long long s[1001][1001],f[1001],ss;
15 void add(int u,int v,long long dis)
16 {
17     num++;
18     edge[num].next=head[u];
19     head[u]=num;
20     edge[num].to=v;
21     edge[num].dis=dis;
22 }
23 int spfa(int u,int v)
24 {
25     memset(dist,127/3,sizeof(dist));
26     ss=dist[1];
27     memset(vis,0,sizeof(vis));
28     int h=0,t=1,i;
29     q[1]=1;
30     dist[1]=0;
31     while (h<t)
32     {
33         h++;
34         int x=q[h];
35         vis[x]=0;
36         for (i=head[x];i;i=edge[i].next)
37         {
38             int y=edge[i].to;
39              if (b[y][v]-b[y][u-1]==0&&dist[y]>dist[x]+edge[i].dis)
40              {
41                  dist[y]=dist[x]+edge[i].dis;
42                   if (!vis[y])
43                   {
44                       vis[y]=1;
45                       t++;
46                       q[t]=y;
47                   }
48              }
49         }
50     }
51     //cout<<dist[m]<<endl;
52     return dist[m];
53 }
54 int main()
55 {int i,j,u,v,dis,x,l,r;
56     cin>>n>>m>>k>>e;
57     for (i=1;i<=e;i++)
58     {
59         scanf("%d%d%d",&u,&v,&dis);
60         add(u,v,dis);
61         add(v,u,dis);
62     }
63     cin>>d;
64      for (i=1;i<=d;i++)
65      {
66       scanf("%d%d%d",&x,&l,&r);
67        for (j=l;j<=r;j++)
68         b[x][j]=1;
69      }
70      for (i=1;i<=m;i++)
71      {
72          for (j=1;j<=n;j++)
73           b[i][j]+=b[i][j-1];
74      }
75       for (i=1;i<=n;i++)
76       {
77           for (j=i;j<=n;j++)
78            s[i][j]=spfa(i,j);
79       }
80      for (i=1;i<=n;i++)
81      {
82          f[i]=s[1][i]*i;
83          for (j=0;j<i;j++)
84          if (s[j+1][i]!=ss)
85          f[i]=min(f[i],f[j]+s[j+1][i]*(i-j)+k);
86      }
87     cout<<f[n];
88 }

 

[ZJOI2006]物流运输