题目
FJ的农场有n个小镇, 奶牛bessi在小镇0,它的学校在小镇n-1. bessi要坐车到学校去上学. N个小镇之间有公交车, bessi就是坐公交车去上学. 小镇之间有m部公交车,我们用(a, b, leave, time, cost) 来描述一部公交车的信息: 表示有一部公交车在时刻leave从小镇a出发, 经过time分钟到达城市b, 车票价格是cost. 由于bessi今天睡过头了,他希望在t分钟以内(包括t分钟)从小镇0到达小镇n-1. 他应该怎样坐公交车才能用最少的车费又能准时上学? 注意: 若bessi在时刻x刚好到达小镇a, 如果公交车的出发时刻也恰好是时刻x, 那么我们规定bessi无法坐到该公交车,也就是说如果想坐这趟公交车则必须在时刻x之前到达小镇a. 当然,有一种情况例外, 小镇0的公交车如果是0时刻出发, bessi在时刻0是可以坐这趟公交车的. 0时刻bessi在小镇0处.
题解
我的想法是二分花费,然后Spfa判断花费是否可行
但是正解是DP,其实正解的DP和Spfa应该是一个意思,只是表达方式不同
DP数组的定义十分的套路:f[i,j]表示i时刻到达j小镇的最小话费
然后仍旧十分套路的考虑正推还是反推,为了方便正解考虑正推,也就是考虑当前情况已经得出答案,要由当前情况推出下一情况
接下来还是十分套路的考虑对情况进行分类,套路地分出留在这个点和从第k条路去往另一个点,于是:
i 0—t
j 1—n-1
k 1—m
a[k]=j leave[k]=i leave[k]+time[k]+1<=t —>f[leave[k]+time[k]+1,b[k]]=f[i,j] 走
f[i+1,j]=min(f[i,j],f[i+1,j]) 留
代码
var
a,b,l,t,c:array[1..50]of longint;
f:array[0..10001,0..50]of longint;
n,m,s,i,j,k:longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
readln(n,s,m);
for i:=1 to m do
readln(a[i],b[i],l[i],t[i],c[i]);
fillchar(f,sizeof(f),$7f);
f[0,0]:=0;
for i:=0 to s do
for j:=0 to n-1 do
begin
if f[i,j]=f[0,50] then continue;
for k:=1 to m do
if (a[k]=j)and(i=l[k])and(l[k]+t[k]<=s+1) then
f[l[k]+t[k]+1,b[k]]:=min(f[l[k]+t[k]+1,b[k]],f[i,j]+c[k]);
f[i+1,j]:=min(f[i+1,j],f[i,j]);
end;
if f[s+1,n-1]=f[0,50] then writeln(-1) else writeln(f[s+1,n-1]);
end.