分治:旅行家的预算(travel)

旅行家的预算(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
若无,--->4
3: 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.
原文地址:https://www.cnblogs.com/spiderKK/p/4301214.html