[ZJOI2006]物流運輸 --- dp +最短路
阿新 • • 發佈:2019-02-08
題目描述
物流公司要把一批貨物從碼頭運到碼頭。由於貨物量比較大,需要n天才能運完。貨物運輸過程中一般要轉停好幾個碼頭。物流公司通常會設計一條固定的運輸路線,以便對整個運輸過程實施嚴格的管理和跟蹤。由於各種因素的存在,有的時候某個碼頭會無法裝卸貨物。這時候就必須修改運輸路線,讓貨物能夠按時到達目的地。但是修改路線是—件十分麻煩的事情,會帶來額外的成本。因此物流公司希望能夠訂一個天的運輸計劃,使得總成本儘可能地小。
分析
還真不該看標籤的,還以為是用跑來著。其實就是一個簡單的dp,只不過要用最短路來處理需要的資料罷了。
令表示前天用的最小成本,則
其中表示第天到第天的走同一條路的最小成本
程式碼
#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;
}