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

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

題目描述

物流公司要把一批貨物從碼頭AA運到碼頭BB。由於貨物量比較大,需要n天才能運完。貨物運輸過程中一般要轉停好幾個碼頭。物流公司通常會設計一條固定的運輸路線,以便對整個運輸過程實施嚴格的管理和跟蹤。由於各種因素的存在,有的時候某個碼頭會無法裝卸貨物。這時候就必須修改運輸路線,讓貨物能夠按時到達目的地。但是修改路線是—件十分麻煩的事情,會帶來額外的成本。因此物流公司希望能夠訂一個nn天的運輸計劃,使得總成本儘可能地小。

分析

還真不該看標籤的,還以為是用spfaspfadpdp來著。其實就是一個簡單的dp,只不過要用最短路來處理需要的資料罷了。
f[i]f[i]

i]表示前ii天用的最小成本,則f[i]=min(f[i],f[j1]+k+d)f[i] = min(f[i], f[j - 1] + k + d)
其中dd表示第jj天到第ii天的走同一條路的最小成本

程式碼

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>

#define IL inline

using namespace std;

IL int read()
{
    char
c = getchar(); int sum = 0 ,k = 1; for(;'0' > c || c > '9'; c = getchar()) if(c == '-') k = -1; for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0'; return sum * k; } int n, m, k; int to[10005], nxt[10005], val[10005]; int cnt, last[105]; IL void add(int
u, int v, int w) { to[++cnt] = v; nxt[cnt] = last[u]; last[u] = cnt; val[cnt] = w; } int close[25][105]; int dis[25]; bool vis[25]; int f[105]; queue<int>Q; IL int min_(int x, int y) { return x < y ? x : y; } IL int spfa(int l, int r) { if(close[1][r] - close[1][l - 1] || close[m][r] - close[m][l - 1]) return 0x3f3f3f3f; memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; Q.push(1); for(int u; !Q.empty();) { u = Q.front(); Q.pop(); vis[u] = 0; for(int i = last[u], v; (v = to[i]); i = nxt[i]) if(!(close[v][r] - close[v][l - 1]) && dis[v] > dis[u] + val[i]) { dis[v] = dis[u] + val[i]; if(!vis[v]) { vis[v] = 1; Q.push(v); } } } if(dis[m] == 0x3f3f3f3f) return dis[m]; return dis[m] * (r - l + 1); } int main() { n = read(); m = read(); k = read(); for(int i = read(), x, y, z; i; --i) { x = read(); y = read(); z = read(); add(x, y, z); add(y, x, z); } for(int i = read(), p, l, r; i; --i) { p = read(); l = read(); r = read(); for(; l <= r; ++l) close[p][l] = 1; } for(int i = 1; i <= m; ++i) for(int j = 2; j <= n; ++j) close[i][j] += close[i][j - 1]; memset(f, 0x3f, sizeof(f)); f[0] = -k; for(int i = 1, d; i <= n; ++i) for(int j = 1; j <= i; ++j) { d = spfa(j, i); if(d == 0x3f3f3f3f) continue; f[i] = min_(f[i], f[j - 1] + k + d); } printf("%d\n", f[n]); return 0; }