BZoj 1003 物流运输 DP+最短路

2013-09-11 09:56

W[I]代表前I天能取得的最小花费,假设在第J天更改一次路线,那么如果有

W[I]>W[J]+第j+1到第I天的最小花费+更改路线的花费(K) 那么更新W[I];

用最短路求第J+1到I的最短路*(I-J),边界则是W[1]=0;

因为最开始的路线不用更改(就是最初的路线不算在更改的费用中),这个

方程默认第一次的路线就是更改后的,多加了一次K,所以最后输出W[I]-K;

//By BLADEVIL
var
    connect                 :array[0..110,0..110] of longint;
    n, m, k, e, ch          :longint;
    c                       :array[0..110,0..110] of longint;
    w                       :array[0..110] of longint;
    d                       :array[0..110] of longint;
    vis                     :array[0..1100] of boolean;

procedure init;
var
    i, j                    :longint;
    x, y, z                 :longint;
begin
assign(input,'santajs.in'); reset(input);
assign(output,'santajs.out'); rewrite(output);
    read(n,m,k,e);
    fillchar(connect,sizeof(connect),10);
    for i:=1 to e do
    begin
        read(x,y,z);
        if z<connect[x,y] then
        begin
            connect[x,y]:=z;
            connect[y,x]:=z;
        end;
    end;
    read(ch);
    for i:=1 to ch do
    begin
        read(x,y,z);
        for j:=y to z do
        begin
            inc(c[j,0]);
            c[j,c[j,0]]:=x;
        end;
    end;
end;

function dijkstra(s,t:longint):longint;
var
    i, j, max, k            :longint;
begin
    fillchar(vis,sizeof(vis),false);
    for i:=1 to m do d[i]:=maxlongint;
    d[1]:=0;
    for i:=s to t do
        for j:=1 to c[i,0] do
            vis[c[i,j]]:=true;

    for i:=1 to m-1 do
    begin
        max:=maxlongint;
        for j:=1 to m do
            if (not vis[j]) and (d[j]<max) then
            begin
                k:=j;
                max:=d[j];
            end;
            vis[k]:=true;
            for j:=1 to m do if d[j]>d[k]+connect[k,j] then d[j]:=d[k]+connect[k,j];
    end;
    exit(d[m]);
end;


procedure dp;
var
    i, j, x                 :longint;
begin
    for i:=1 to n do
    begin
        w[i]:=maxlongint div 10;
        for j:=0 to i-1 do
        begin
            x:=dijkstra(j+1,i);
            if x>100000000 then continue;
            if w[i]>w[j]+k+(i-j)*x then w[i]:=w[j]+k+(i-j)*x;
        end;
    end;
    writeln(w[n]-k);
close(input); close(output);
end;

begin
    init;
    dp;
end.

 

posted on 2013-11-20 14:19  BLADEVIL  阅读(243)  评论(0编辑  收藏  举报