物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是一件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。
【题解】
DP+SPFA,因为数据很小所以可以暴力,主要还是练习一下算法
【代码】
program p1003;
type
td = record
st, ed: longint;
end;
var
f: array[0..105] of int64;
a: array[0..20, 0..20] of int64;
b: array[0..20] of longint;
c: array[0..20, 0..20] of td;
q: array[0..20] of longint;
d0: array[0..20] of int64;
pd: array[0..20] of boolean;
n, m, e, d, i, j, x, y, p: longint;
k, l: int64;
function ck(m, x, y: longint): boolean;
var
i: longint;
begin
ck := True;
for i := 1 to b[m] do
if ((x <= c[m, i].st) and (c[m, i].st <= y)) or
((x <= c[m, i].ed) and (c[m, i].ed <= y) or
((c[m, i].st < x) and (c[m, i].ed > y))) then
exit(False);
end;
function SPFA(e, b: longint): int64;
var
head, i, j, tail: longint;
begin
for i := 1 to 20 do
d0[i] := 1073741824;
for i := 1 to 20 do
pd[i] := False;
head := 0;
tail := 1;
q[tail] := 1;
d0[1] := 0;
pd[1] := True;
repeat
Inc(head);
if head = 21 then
head := 1;
j := q[head];
pd[j] := False;
for i := 1 to m do
if i <> j then
if ck(i, b, e) then
if (a[j, i] > 0) and (int64(d0[j] + a[j, i]) < d0[i]) then
begin
d0[i] := int64(d0[j] + a[j, i]);
if not pd[i] then
begin
pd[i] := True;
Inc(tail);
if tail = 21 then
tail := 1;
q[tail] := i;
end;
end;
until head = tail;
exit(d0[m]);
end;
begin
fillchar(a, sizeof(a), 0);
fillchar(b, sizeof(b), 0);
readln(n, m, k, e);
for i := 1 to e do
begin
readln(x, y, p);
if (a[x, y] = 0) or (p < a[x, y]) then
begin
a[x, y] := p;
a[y, x] := p;
end;
end;
readln(d);
for i := 1 to d do
begin
readln(p, x, y);
Inc(b[p]);
c[p, b[p]].st := x;
c[p, b[p]].ed := y;
end;
f[0] := -k;
for i := 1 to 105 do
f[i] := 1073741824;
for i := 1 to n do
for j := 0 to i - 1 do
begin
l := f[j] + int64(SPFA(i, j + 1) * int64(i - j)) + k;
if l < f[i] then
f[i] := l;
end;
writeln(f[n]);
end.