zoukankan      html  css  js  c++  java
  • 1003. [ZJOI2006]物流运输【区间DP+最短路】

    Description

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

    Input

      第一行是四个整数n(1<=n<=100)、m(1<=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的运输路线。

    Output

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

    Sample Input

    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

    Sample Output

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

    这个题的IDEA……也炒鸡妙啊……
    (可能是我太SB了……没看数据就以为是什么SPFA的新操作……)
    结果看了范围(题解)才意识到smg啊……这范围一看都不是单纯的最短路好吧……
    其实这个题是由DP和SPFA两部分构成的……然而其实这两部分都特别简单……
    用Len[i][j]表示i到j天都用一条路的最短路,这个可以用多次SPFA求
    然后DP求解,方程就很好想了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<queue>
     7 #define INF (1061109567)
     8 using namespace std;
     9 
    10 int head[201],num_edge;
    11 int Day[201][201],f[201],Len[201][201];
    12 int num[201],dis[201];
    13 int n,m,k,e;
    14 bool used[201];
    15 queue <int> q;
    16 
    17 struct node
    18 {
    19     int to;
    20     int next;
    21     int len;
    22 }edge[1001];
    23 
    24 void add(int u,int v,int l)
    25 {
    26     edge[++num_edge].to=v;
    27     edge[num_edge].next=head[u];
    28     edge[num_edge].len=l;
    29     head[u]=num_edge;
    30 }
    31 
    32 int SPFA(int x,int y)
    33 {
    34     memset(used,false,sizeof(used));
    35     memset(dis,0x3f,sizeof(dis));
    36     for (int i=x;i<=y;++i)
    37         for (int j=1;j<=num[i];++j)
    38             used[Day[i][j]]=true;
    39     dis[1]=0;
    40     used[1]=true;
    41     q.push(1);
    42     while (!q.empty())
    43     {
    44         int x=q.front();
    45         q.pop();
    46         for (int i=head[x];i!=0;i=edge[i].next)
    47         {
    48             if (dis[edge[i].to]>dis[x]+edge[i].len)
    49             {
    50                 dis[edge[i].to]=dis[x]+edge[i].len;
    51                 if (!used[edge[i].to])
    52                 {
    53                     used[edge[i].to]=true;
    54                     q.push(edge[i].to);
    55                 }
    56             }
    57         }
    58         used[x]=false;
    59     }
    60     return dis[m];
    61 }
    62 
    63 int main()
    64 {
    65     int u,v,l,d,p,a,b;
    66     scanf("%d%d%d%d",&n,&m,&k,&e);
    67     for (int i=1;i<=e;++i)
    68     {
    69         scanf("%d%d%d",&u,&v,&l);
    70         add(u,v,l);
    71         add(v,u,l);
    72     }
    73     scanf("%d",&d);
    74     for (int i=1;i<=d;++i)
    75     {
    76         scanf("%d%d%d",&p,&a,&b);
    77         for (int j=a;j<=b;++j)
    78             Day[j][++num[j]]=p;
    79     }
    80     for (int i=1;i<=n;++i)
    81         for (int j=i;j<=n;++j)
    82             Len[i][j]=SPFA(i,j);
    83     memset(f,0x3f,sizeof(f));        
    84     for (int i=1;i<=n;++i)
    85     {
    86         if (Len[1][i]!=INF)
    87             f[i]=Len[1][i]*i;
    88         for (int j=2;j<=i;++j)
    89             if (Len[j][i]!=INF)
    90                 f[i]=min(f[i],f[j-1]+Len[j][i]*(i-j+1)+k);
    91     }
    92     printf("%d",f[n]);
    93 }
  • 相关阅读:
    Maven最全指南,看了必懂(转载)
    MySQL:数据库优化
    关于 MyBatis 10 种通用的写法
    Redis 性能问题分析(转载)
    前端对于服务端渲染(SSR)的理解
    JS 中的编码和解码(encode和decode)
    SEO、SPA、SSR的区别关系详解
    VUE 项目路由的两种模式(hash、history)
    Chrome和IE浏览器的渲染过程区别
    对于前端缓存的理解(缓存机制和缓存类型)
  • 原文地址:https://www.cnblogs.com/refun/p/8678479.html
Copyright © 2011-2022 走看看