最近懒~~(颓废)~~了好多,又不太更新Blog了......

【题目描述】

物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。

货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。

由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。

但是修改路线是一件十分麻烦的事情,会带来额外的成本。

因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。

【题目链接】

BZOJ 1003 物流运输 【ZJOI 2016】

【解题思路】

动态规划,设$ f[i] $表示前$ i $天的最小成本,转移如下:

如果这$ i $天不改变运输计划,那么: $$ f[i] = cost(1, i) $$

如果改变,那么枚举上一次改变是在第$ j $天,那么: $$ f[i] = min{\ f[j] + cost(j + 1, i) + k, j \in [2, i) } $$

两种情况取个$ min $咯。

其中$ k $是改变运输计划的代价(输入中给出),$ cost(x, y) $表示从第$ x $天到第$ y $天不改变运输计划的最小花费,求一下最短路就可以知道啦。

【AC代码】

#include <cstdio>
#include <algorithm>
#include <climits>
#include <queue>
 
#define MAXN 100
#define MAXM 20
 
struct Range{
    int l, r;
};
 
struct Node{
    struct Edge *edges;
 
    int dist;
    bool inQue;
 
    bool invaild;
 
    std::vector<Range> ranges;
 
    Node() : edges(NULL) {}
 
} nodes[MAXM];
 
struct Edge{
    Node *to;
    Edge *next;
    int w;
 
    Edge(Node *from, Node *to, int w) : to(to), next(from->edges), w(w) {}
};
 
inline void addUEdge(int a, int b, int w){
    Node *u = nodes + a, *v = nodes + b;
    u->edges = new Edge(u, v, w), v->edges = new Edge(v, u, w);
}
 
int m, k;
Node *s, *t;
 
inline int cost(int l, int r){
    for(Node *v = nodes; v != nodes + m; v++){
        v->dist = INT_MAX, v->inQue = false;
        v->invaild = false;
        for(std::vector<Range>::iterator range = v->ranges.begin(); range != v->ranges.end(); range++){
            if(std::max(l, range->l) <= std::min(r, range->r)){
                v->invaild = true;
                break;
            }
        }
    }
 
    std::queue<Node*> Q;
 
    Q.push(s);
    s->dist = 0, s->inQue = true;
 
    while(!Q.empty()){
        Node *v = Q.front(); Q.pop();
        v->inQue = false;
 
        for(Edge *e = v->edges; e; e = e->next) if(!e->to->invaild){
            if(e->to->dist > v->dist + e->w){
                e->to->dist = v->dist + e->w;
                if(!e->to->inQue){
                    Q.push(e->to);
                    e->to->inQue = true;
                }
            }
        }
    }
 
    if(t->dist == INT_MAX) return INT_MAX;
    else return t->dist * (r - l + 1);
}
 
inline void updateMin(int &x, int y){
    x = std::min(x, y);
}
 
int n;
int f[MAXN + 1];
 
inline int dp(){
    for(int i = 1; i <= n; i++){
        f[i] = cost(1, i);
        for(int j = 2; j < i; j++){
            int c = cost(j + 1, i);
            if(c == INT_MAX) continue;
            else updateMin(f[i], f[j] + c + k);
        }
    }
    return f[n];
}
 
int main(){
    // freopen("bzoj_1003.in", "r", stdin), freopen("bzoj_1003.out", "w", stdout);
 
    scanf("%d%d%d", &n, &m, &k);
    s = nodes, t = nodes + m - 1;
 
    int e;
    scanf("%d", &e);
    for(int i = 0; i < e; i++){
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        addUEdge(u, v, w);
    }
 
    int d;
    scanf("%d", &d);
    for(int i = 0; i < d; i++){
        int x, l, r;
        scanf("%d%d%d", &x, &l, &r);
        x--;
        (nodes + x)->ranges.push_back((Range){l, r});
    }
 
    printf("%d\n", dp());
 
    // fclose(stdin), fclose(stdout);
    return 0;
}