• [BZOJ1003](ZJOI 2006) 物流运输trans


    【题目描述】

    物流公司要把一批货物从码头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 = 0;
     21     while(!isdigit(c) && c != '-')c = getchar();
     22     if(c == '-')minus = 1, c = getchar();
     23     x = c - '0';
     24     while(isdigit(c = getchar()))x = x * 10 + c - '0';
     25     if(minus)x = -x;
     26 }
     27 /*======================================================*/
     28 const int maxn = 102, maxm = 21, INF = 0x3f3f3f3f;
     29  
     30 struct event{int T, num; } E[2002];
     31 inline bool operator < (const event &a, const event &b){
     32     return a.T < b.T;
     33 }
     34  
     35 int n, m, K, Ecnt = 0;
     36 int inval[maxn][maxn] = {0}, 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] = {0};
     46 int dis[maxm] = {0};
     47 inline void setinf(){
     48     dis[1] = 0;
     49     for(int i = 2;i <= m;++i)
     50         dis[i] = INF;
     51 }
     52  
     53 inline void pushQ(int x){
     54     vector<edge>::iterator it;
     55     for(int i=1, j=2;i <= m;++i, j <<= 1)
     56         if(x & j){
     57             if(!inQ[i])Q.push(i), inQ[i] = 1;
     58             for(it = adj[i].begin();it != adj[i].end();++it)
     59                 if(!inQ[it->to])Q.push(it->to), inQ[it->to] = 1;
     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] = 0;
     68         for(it = adj[t].begin();it != adj[t].end();++it)
     69             if((!(inval[l][r] & (1 << 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] = 1;
     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+1, E[Ecnt].num = k; ++Ecnt;
     91     }
     92     sort(E, E + Ecnt);
     93     for(j = 0, i = 1;i <= n;++i){
     94         inval[i][i] = inval[i-1][i-1];
     95         while(j < Ecnt && E[j].T == i){
     96             inval[i][i] ^= (1 << E[j].num);
     97             ++j;
     98         }
     99     }
    100     for(i = 1;i < n;++i)
    101         for(j = i+1;j <= n;++j)
    102             inval[i][j] = inval[i][j-1] | inval[j][j];
    103     for(i = 1;i <= n;++i){
    104         setinf();
    105         Q.push(1), inQ[1] = 1;
    106         cost[i][n] = spfa(i, n);
    107         for(j = n-1;j >= i;--j){
    108             if(inval[i][j] == inval[i][j+1]){
    109                 cost[i][j] = cost[i][j+1];
    110                 continue;
    111             }
    112             pushQ(inval[i][j] ^ inval[i][j+1]);
    113             if(!inQ[1])Q.push(1), inQ[1] = 1;
    114             cost[i][j] = spfa(i, j);
    115         }
    116     }
    117      
    118 }
    119  
    120 inline void work(){
    121     int i, j, c;
    122     for(i = 1;i <= n;++i)
    123         dp[i] = cost[1][i] == INF ? INF : cost[1][i] * i;
    124     for(i = 2;i <= n;++i) for(j = 1;j < i;++j){
    125         if(cost[j+1][i] == INF)continue;
    126         c = dp[j] + cost[j+1][i] * (i - j) + K;
    127         if(c < dp[i])
    128             dp[i] = c;
    129     }
    130     printf("%d ", dp[n]);
    131 }
    132      
    133 int main(){
    134     #if defined DEBUG
    135     freopen("test""r", stdin);
    136     #else
    137     //freopen("bzoj_1002.in", "r", stdin);
    138     //freopen("bzoj_1002.out", "w", stdout);
    139     #endif
    140     init();
    141      
    142     work();
    143      
    144     #if defined DEBUG
    145     cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
    146     #endif
    147     return 0;
    148 }
    spfa预处理+DP
  • 相关阅读:
    Freemaker:操作集合
    win10:在关闭防火墙下如何屏蔽特定端口
    win10:家庭版开启组策略
    oracle:10g下载地址(转载)
    mybatis:延迟加载时不要在get/set方法上面添加final关键字(原创)
    mybatis:在springboot中的配置
    mybatis:访问静态变量或方法
    maven:手动安装JAR到本地仓库
    datatables日常使用集合
    python 装饰器
  • 原文地址:https://www.cnblogs.com/Asm-Definer/p/4122200.html
Copyright © 2020-2023  润新知