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
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
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.
var f:Array[1..100,1..100] of longint;
//============================================================================
procedure init;
var e,i,x,y,z:longint;
begin
end;
//============================================================================
function dij:longint;
var i,j,min,int,now:longint;
begin
end;
//============================================================================
procedure predone;
var i,j,k,g:longint;
begin
end;
//============================================================================
function min(x,y:longint):longint;
begin
end;
//============================================================================
procedure dpp;
var i,j:longint;
begin
end;
//============================================================================
begin
end.