【题目描述】

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

【输入格式】

第一行是四个整数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的运输路线。

【输出格式】

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

【样例输入】

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

【样例输出】

32

【提示】

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

【分析】

用最短路作为权值的区间覆盖问题。可以用spfa预处理出每个区间中“整体可行”的路线中的最短路,然后用动态规划求解。

这样看来,预处理阶段需要对$O(n^2)$个区间进行计算,对于每个区间还要扫描出这个区间哪些节点“可以访问”, 时间可能会有些不够用。怎么办呢?

事实上,这种思路还有很大的优化空间。首先,节点数最多只有20,我们可以用一个32位整数存储当前区间可以访问的节点集合,通过位运算很容易就可以求出这些集合。接着,我们可以优化一下进行spfa的顺序:从小到大枚举区间左端点,再从大到小枚举右端点。这样,在每轮第二层循环中,由于区间规模在缩小,“可以访问的节点”集合规模是单调递增的,于是我们可以仅在第一层循环开始时更新dis数组,然后在第二层循环中判断可访问节点数是否有增加,若有,就将这些节点的邻接点加入队列再进行spfa,否则就直接将上次spfa的dis值当做这一区间的权值。

采用了这种预处理方法后,我的代码在bzoj上运行时间为24ms(大概是因为STL拖慢了速度?反正我知道低于20ms的代码都是2012年以前提交的……)

预处理完成后,剩下的就是一个$O(n)$状态、$O(n)$转移的简单DP了,这里不再赘述。

  1 /**************************************************************
  2     Problem: 1003
  3     User: Asm.Def
  4     Language: C++
  5     Result: Accepted
  6     Time:24 ms
  7     Memory:1376 kb
  8 ****************************************************************/
  9  
 10 #include <iostream>
 11 #include <cctype>
 12 #include <cstdio>
 13 #include <vector>
 14 #include <algorithm>
 15 #include <cmath>
 16 #include <queue>
 17 using namespace std;
 18 inline void getd(int &x){
 19     char c = getchar();
 20     bool minus = ;
 21     while(!isdigit(c) && c != '-')c = getchar();
 22     if(c == '-')minus = , c = getchar();
 23     x = c - '';
 24     while(isdigit(c = getchar()))x = x *  + c - '';
 25     if(minus)x = -x;
 26 }
 27 /*======================================================*/
 28 const int maxn = , maxm = , INF = 0x3f3f3f3f;
 29  
 30 struct event{int T, num; } E[];
 31 inline bool operator < (const event &a, const event &b){
 32     return a.T < b.T;
 33 }
 34  
 35 int n, m, K, Ecnt = ;
 36 int inval[maxn][maxn] = {}, cost[maxn][maxn], dp[maxn];
 37  
 38 struct edge{
 39     int to, w;
 40     edge(int t, int c):to(t), w(c){}
 41 };
 42 vector<edge> adj[maxm];
 43  
 44 queue<int> Q;
 45 bool inQ[maxm] = {};
 46 int dis[maxm] = {};
 47 inline void setinf(){
 48     dis[] = ;
 49     for(int i = ;i <= m;++i)
 50         dis[i] = INF;
 51 }
 52  
 53 inline void pushQ(int x){
 54     vector<edge>::iterator it;
 55     for(int i=, j=;i <= m;++i, j <<= )
 56         if(x & j){
 57             if(!inQ[i])Q.push(i), inQ[i] = ;
 58             for(it = adj[i].begin();it != adj[i].end();++it)
 59                 if(!inQ[it->to])Q.push(it->to), inQ[it->to] = ;
 60         }
 61 }
 62  
 63 inline int spfa(int l, int r){
 64     vector<edge>::iterator it;
 65     int t;
 66     while(!Q.empty()){
 67         t = Q.front(); Q.pop(); inQ[t] = ;
 68         for(it = adj[t].begin();it != adj[t].end();++it)
 69             if((!(inval[l][r] & ( << it->to))) && dis[it->to] > dis[t] + it->w){
 70                 dis[it->to] = dis[t] + it->w;
 71                 if(!inQ[it->to])
 72                     Q.push(it->to), inQ[it->to] = ;
 73             }
 74     }
 75     return dis[m];
 76 }
 77  
 78 inline void init(){
 79     int i, j, e, k, d;
 80     getd(n), getd(m), getd(K), getd(e);
 81     while(e--){
 82         getd(i), getd(j), getd(k);
 83         adj[i].push_back(edge(j, k));
 84         adj[j].push_back(edge(i, k));
 85     }
 86     getd(d);
 87     while(d--){
 88         getd(k), getd(i), getd(j);
 89         E[Ecnt].T = i, E[Ecnt].num = k; ++Ecnt;
 90         E[Ecnt].T = j+, E[Ecnt].num = k; ++Ecnt;
 91     }
 92     sort(E, E + Ecnt);
 93     for(j = , i = ;i <= n;++i){
 94         inval[i][i] = inval[i-][i-];
 95         while(j < Ecnt && E[j].T == i){
 96             inval[i][i] ^= ( << E[j].num);
 97             ++j;
 98         }
 99     }
     for(i = ;i < n;++i)
         for(j = i+;j <= n;++j)
             inval[i][j] = inval[i][j-] | inval[j][j];
     for(i = ;i <= n;++i){
         setinf();
         Q.push(), inQ[] = ;
         cost[i][n] = spfa(i, n);
         for(j = n-;j >= i;--j){
             if(inval[i][j] == inval[i][j+]){
                 cost[i][j] = cost[i][j+];
                 continue;
             }
             pushQ(inval[i][j] ^ inval[i][j+]);
             if(!inQ[])Q.push(), inQ[] = ;
             cost[i][j] = spfa(i, j);
         }
     }
      
 }
  
 inline void work(){
     int i, j, c;
     for(i = ;i <= n;++i)
         dp[i] = cost[][i] == INF ? INF : cost[][i] * i;
     for(i = ;i <= n;++i) for(j = ;j < i;++j){
         if(cost[j+][i] == INF)continue;
         c = dp[j] + cost[j+][i] * (i - j) + K;
         if(c < dp[i])
             dp[i] = c;
     }
     printf("%d\n", dp[n]);
 }
      
 int main(){
     #if defined DEBUG
     freopen("test", "r", stdin);
     #else
     //freopen("bzoj_1002.in", "r", stdin);
     //freopen("bzoj_1002.out", "w", stdout);
     #endif
     init();
      
     work();
      
     #if defined DEBUG
     cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
     #endif
     return ;
 }

spfa预处理+DP

[BZOJ1003](ZJOI 2006) 物流运输trans的更多相关文章

  1. ZJOI 2006 物流运输 bzoj1003

    题目描述 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪. ...

  2. [ZJOI 2006]物流运输

    Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...

  3. BZOJ-1003 物流运输trans SPFA+DP

    傻逼错误耗我1h,没给全范围坑我1A.... 1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec Memory Limit: 162 MB Submit: 529 ...

  4. bzoj1003[ZJOI2006]物流运输trans

    1003: [ZJOI2006]物流运输trans Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常 ...

  5. 【BZOJ】【1003】【ZJOI2006】物流运输trans

    最短路/DP 这题数据规模并不大!!这是重点……… 所以直接暴力DP就好了:f[i]表示前 i 天的最小花费,则有$f[i]=min\{f[j]+cost[j+1][i]+k\} (0\leq j \ ...

  6. BZOJP1003 [ZJOI2006]物流运输trans

    BZOJP1003 [ZJOI2006]物流运输trans 1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec  Memory Limit: 162 MB Sub ...

  7. BZOJ 1003 [ZJOI2006]物流运输trans

    1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4242  Solved: 1765[Submit] ...

  8. BZOJ 1003: [ZJOI2006]物流运输trans(最短路+dp)

    1A,爽! cost[i][j]表示从第i天到第j天不改路线所需的最小花费,这个可以用最短路预处理出.然后dp(i)=cost[j][i]+dp(j-1)+c. c为该路线的花费. --------- ...

  9. BZOJ 1003 物流运输trans dijstra+dp

    1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3896  Solved: 1608[Submit] ...

随机推荐

  1. Xmind 8 update5 破解

    Step 1. Download XMind Step 2. Run XMind at least once after installation, xmind will init the confi ...

  2. <摘录>Fedora添加国内源和本地源

    <摘录>Fedora添加国内源和本地源 http://www.cnblogs.com/hummersofdie/p/3915070.html fedora的软件源信息文件(*.repo)都 ...

  3. tcp 在调用connect失败后要不要重新socket

    tcp 在调用connect失败后要不要重新socket http://blog.csdn.net/occupy8/article/details/48253251

  4. 《gdb调试之基础篇》

    <gdb调试之基础篇> http://blog.csdn.net/miss_acha/article/details/42346543

  5. 【bzoj3545】peaks

    离线一下,动态开点+线段树合并,然后权值线段树上询问kth即可. #include<bits/stdc++.h> ; *; using namespace std; ; inline in ...

  6. swift 动态获取类, 获取命名空间

    在做swift开发中很多时候会动态加载控制器的类, 可以让app更加灵活显示界面信息 一般情况下都是服务器返回显示的控制器类name然后动态显示, 但是服务器返回的类name是string, 怎么转换 ...

  7. 阿里云ECS的使用

    一.阿里云ECS的使用 1.Linux CentOS Ubuntu Readhat 2.远程登录 xshell 远程登录 winScp 远程文件操作 3.Linux命令 cd 目录名 ls . ls ...

  8. android studio 64位手机+Fresco引起的在arm64位机器上找不到对应的so库

    我们的程序在32位机器上没有问题,有一天公司采购了一台魅族MX5 MTK的64位处理器上我们的应用报错了 "nativeLibraryDirectories=[/data/app/com.l ...

  9. JavaScript中对象的属性类型

    JavaScript中,对象的属性有两种:数据属性和访问器属性. 数据属性 特性: 数据属性包括一个数据值的位置.在这个位置可以读取和写入值.数据属性有4个特性. [[configurable]]:可 ...

  10. Freemarker的页面和JS遍历后台传入的Map

    后端传到前端的Map Freemarker页面遍历Map: JS遍历Map: