1. 程式人生 > >1003: [ZJOI2006]物流運輸[最短路+dp]

1003: [ZJOI2006]物流運輸[最短路+dp]

題意:存在有m個碼頭,修改運輸成本k,以及e條路,讓設計一條n天的路線,使得花費最小,每一條路線都是從頭跑到尾。


題解:我們可以先到設計 f [ i ] f[i] 表示從第一天到第 i

i 天的最小花費, t [ i ] [ j ] t[i][j]
表示第 i i 天到第 j j 天從1->n的最短路是多少,通過dijkstra或者spfa都能跑出來,需要標記在 [
i , j ] [i, j]
天內哪些碼頭能用,然後通過dp來轉移,轉移方程如下:
f [ i ] = m i n ( f [ i ] , f [ j ] + k + t [ j + 1 ] [ i ] ( i j ) ) f[i] = min(f[i], f[j] + k + t[j + 1][i] * (i - j)) 表示轉了路線一次,剩下的 i j (i-j) 天走 t [ j + 1 ] [ i ] t[j+1][i]


a c   c o d e : ac\ code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define g getchar()
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;

inline int read() {
    int res = 0, f = 1; char ch = g;
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = g;}
    while(ch >= '0' && ch <= '9') {res = res * 10 + ch - '0'; ch = g;}
    return res;
}

struct Edge {
    int to, next, val;
} e[maxn];

int h[maxn], d, n, k, m, cnt;

ll f[200], t[200][200];
int flag[200][200];

void add(int u, int v, int w) {
    e[cnt].to = v;
    e[cnt].val = w;
    e[cnt].next = h[u];
    h[u] = cnt++;
}

int spfa(int l, int r) {
    int lim[maxn], vis[maxn], dis[maxn];
    met(lim, 0);
    met(vis, 0);
    for(int i = 1; i <= n; i++) dis[i] = inf;
    rep(i, 1, n) rep(j, l, r) if(flag[i][j]) lim[i] = 1;
    queue<int> q;
    q.push(1);
    dis[1] = 0;
    vis[1] = 1;
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(register int i = h[u]; ~i; i = e[i].next) {
            int v = e[i].to;
            if(!lim[v] && dis[v] > dis[u] + e[i].val) {
                dis[v] = dis[u] + e[i].val;
                if(!vis[v]) {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
        vis[u] = 0;
    }
    return dis[n];
}

int main() {
    met(h, -1);
    cnt = 0;
    d = read(); n = read(); k = read(); m = read();
    int u, v, w;
    rep(i, 1, m) {
        u = read(), v = read(), w = read();
        add(u, v, w); add(v, u, w);
    }
    int x = read();
    int l, r, p;
    while(x--) {
        p = read(), l = read(), r = read();
        for(register int i = l; i <= r; i++) flag[p][i] = 1;
    }
    rep(i, 1, d) rep(j, 1, d) t[i][j] = spfa(i, j);
    rep(i, 1, d) {
        f[i] = (ll)t[1][i] * (ll)i;
        rep(j, 0, i) {
            f[i] = min(f[i], k + f[j] + t[j + 1][i] * (i - j));
        }
    }
    printf("%lld\n", f[d]);
    return 0;
}