旅行家的预算(Travel)
【问题描述】
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格 Pi( i=l,2,...N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
【输入数据】
第一行:D1 C D2 P N,其含义与题目描述中一致。
接下来N行,每行2个数Di Pi,其含义同样与题目描述中一致。
【输出数据】
仅一行,为最小费用
【输入样例】
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
【输出样例】
26.95 1: 判断无解,只要相邻两个加油站的距离大于(汽车油箱的容量C*每升汽油能行驶的距离D2),则输出‘No Solution‘2: 从当前可到达的点中,寻找第一个价格低于当前点价格的油站。 若有,--->3 若无,--->43: s:=s+[(d[i]-d[当前])/D2-rest]*p[当前] rest:=0; 以i为当前点递归第二步4: 判断是否可以到终点 {C*D2<?>D1} 若可:--->5; 若不可:--->6;5: 直接到终点; s:=s+[(D1-d[当前])/D2-rest]*p[当前] 退出6: 寻找在可到达的范围内油价最低的点{加满油} s:=s+(c-rest)*p[当前] 以i为当前点递归第二步//为避免出题人太变态,我在操作前加了快排,好像没用。。。。。。
var distance,c,d,p:double; n:longint; dd:array[1..1000]of double; pp:array[1..1000]of double; i,j,k:longint; s,rest:double; have:boolean; min:real; minx:longint;
procedure qsort(x,y:longint); var s,t:longint; k,temp:double; begin s:=x; t:=y; k:=dd[(x+y) div 2]; while s<t do begin while dd[s]<k do inc(s); while k<dd[t] do dec(t); if s<=t then begin temp:=dd[s]; dd[s]:=dd[t]; dd[t]:=temp; temp:=pp[s]; pp[s]:=pp[t]; pp[t]:=temp; inc(s); dec(t); end; end; if s<y then qsort(s,y); if x<t then qsort(x,t); end;
procedure try(x:longint); var i,j,k:longint; can:boolean; min:real; minx:longint; begin i:=x; can:=false; while i<n do begin inc(i); if (c*d>dd[i]-dd[x])and (pp[i]<pp[x]) then begin k:=i; can:=true; i:=n; end; end; if can then begin s:=s+((dd[k]-dd[x])/d-rest)*pp[x]; rest:=0; try(k); end else begin if distance-dd[x]<c*d then begin s:=s+((distance-dd[x])/d-rest)*pp[x]; writeln(s:0:2); halt; end else begin min:=maxlongint; for i:=x+1 to n do if (c*d>dd[i]-dd[x])and (pp[i]<min) then begin min:=pp[i]; minx:=i; end; s:=s+(c-rest)*pp[x]; rest:=c-(dd[minx]-dd[x])/d; try(minx); end; end; end;
begin readln(distance,c,d,p,n); for i:=1 to n do readln(dd[i],pp[i]); qsort(1,n); s:=0; if dd[1]>c*d then begin writeln(‘No Solution‘); close(input); close(output); halt; end; for i:=2 to n do if dd[i]-dd[i-1]>c*d then begin writeln(‘No Solution‘); halt; end; i:=0; have:=false; while i<n do begin inc(i); if (c*d>dd[i])and (pp[i]<p) then begin k:=i; have:=true; i:=n; end; end; if have then begin s:=dd[k]/d*p; rest:=0; try(k); end else begin if distance<c*d then begin s:=distance/d*p; writeln(s:0:2); halt; end else begin min:=maxlongint; for i:=1 to n do if (c*d>dd[i])and (pp[i]<min) then begin min:=pp[i]; minx:=i; end; s:=c*p; rest:=c-dd[minx]/d; try(minx); end; end;end.
时间: 2024-10-06 11:43:54