[ZJOI2006]物流运输trans

Time Limit: 10 Sec    Memory Limit: 162 MB

Description

物流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是一件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。

Input

第一行是四个整数n(1<=n<=100)、m(1<=m<=20)、K和e。n表示货物运输所需天数,m表示码头总数,K表示每次修改运输路线所需成本。接下来e行每行是一条航线描述,包括了三个整数,依次表示航线连接的两个码头编号以及航线长度(>0)。其中码头A编号为1,码头B编号为m。单位长度的运输费用为1。航线是双向的。再接下来一行是一个整数d,后面的d行每行是三个整数P( 1 < P < m)、a、b(1 < = a < = b < = n)。表示编号为P的码头从第a天到第b天无法装卸货物(含头尾)。同一个码头有可能在多个时间段内不可用。但任何时间都存在至少一条从码头A到码头B的运输路线。

Output

包括了一个整数表示最小的总成本。总成本=n天运输路线长度之和+K*改变运输路线的次数。

Sample Input

5 5 10 8
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5

Sample Output

Sample Output
32
 
题意就如题所示了!
这道题纠结了我很久。毕竟太久没有自己做题了。。。一开始一直都是以一天为单位考虑的。也想到了用最短路加动规做的。可是一直就想不明白一点:一条在每一天都不是最短路的路径有可能是最优的路径,一直从开始用到结束。因为换最短路的改变费用有可能很大,这样次短路从第一天用到最后一天的费用就会比中途更换为最短路的费用低。
可是!天数不能一天一天地考虑,应该一段一段地考虑!!!
因为要得到最优费用。所选择的路径一定是某一段时间内的最短路!!!!
以上那种情况:“一条在每一天都不是最短路的路径有可能是最优的路径,一直从开始用到结束。”
这种情况中每天都不是最短路的路是从第一天到最后一天的一整段时间中的最短路!
好,弄清楚了这点后,一切就很明了。
状态转移方程:dp[i]:=min{dp[j]+f[j+1,i]+k,dp[i]}  (0<=j<i)
(不改变航线的情况可以并入改变的里面考虑。详见:http://zckey163.blog.163.com/blog/static/171346769201082294935394/
f数组可以预处出来。因为数据规模有限,直接搞。
今天WA到爆。究其原因是。。。。是。。。。
输入数据有很多组重边!!!!!!!在读入时要选最小的!!!!!!!!!太猥琐了。。。。。。。。。。
 
 
AC CODE
program hy_1003;
var f:Array[1..100,1..100] of longint;
    s,t:array[1..20,0..4000] of longint;
    d:array[1..20,1..20] of longint;
    dist:array[1..20] of longint;
    dp:array[0..100] of longint;
    p:array[1..20] of boolean;
    n,m,k,size:longint;
//============================================================================
procedure init;
var e,i,x,y,z:longint;
begin
  readln(n,m,k,e);
  for i:=1 to e do
  begin
    readln(x,y,z);
    if (z<d[x,y]) or (d[x,y]=0) then
    begin
      d[x,y]:=z; d[y,x]:=z;
    end;
  end;
  readln(e);
  for i:=1 to e do
  begin
    readln(x,y,z);
    inc(s[x,0]); s[x,s[x,0]]:=y;
    inc(t[x,0]); t[x,t[x,0]]:=z;
  end;
end;
//============================================================================
function dij:longint;
var i,j,min,int,now:longint;
begin
  for i:=1 to m do dist[i]:=maxlongint div 100;
  dist[1]:=0; now:=1; p[1]:=false;
  for i:=1 to m*2 do
  begin
    min:=maxlongint div 100; int:=0;
    for j:=1 to m do
      if p[j] then
      begin
        if (d[now,j]>0) and (dist[now]+d[now,j]<dist[j]) then
        dist[j]:=dist[now]+d[now,j];
        if dist[j]<min then
        begin
          min:=dist[j];
          int:=j;
        end;
      end;
    if int=0 then break; now:=int;
    if now=m then break; p[now]:=false;
  end; exit(dist[m]);
end;
//============================================================================
procedure predone;
var i,j,k,g:longint;
begin
  for i:=1 to n do
    for j:=i to n do
    begin
      for k:=1 to m do
      begin
        p[k]:=true;
        for g:=1 to s[k,0] do
          if (s[k,g]>=i) and (s[k,g]<=j) then
          begin p[k]:=false; break; end;
        if p[k] then
        for g:=1 to t[k,0] do
          if (t[k,g]>=i) and (t[k,g]<=j) then
          begin p[k]:=false; break; end;
        if p[k] then
        for g:=1 to s[k,0] do
          if (s[k,g]<=i) and (t[k,g]>=j) then
          begin p[k]:=false; break; end;
      end; f[i,j]:=dij*(j-i+1);
    end;
end;
//============================================================================
function min(x,y:longint):longint;
begin
  if x<y then min:=x else min:=y;
end;
//============================================================================
procedure dpp;
var i,j:longint;
begin
  dp[0]:=-k;
  for i:=1 to n do
  begin
    dp[i]:=maxlongint div 100;
    for j:=0 to i-1 do
      dp[i]:=min(dp[i],dp[j]+f[j+1,i]+k);
  end;
  writeln(dp[n]);
end;
//============================================================================
begin
  init;
  predone;
  dpp;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值