问题描述
一个旅行家想驾驶汽车以最少的费用从一个城市 到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P 和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,……N)。计算结果四舍五入至小数点后两位。如果无法到达目的 地,则输出“No Solution”。
输入
第一行为4个实数D1、C、D2、P与一个非负整数N;
接下来N行,每行两个实数Di、Pi。
输出
如果可以到达目的地,输出一个实数(四舍五入至小数点后两位),表示最小费用;否则输出“No Solution”(不含引号)。
输入样例
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
输出样例
26.95
思路
运用贪心的策略,尽量多加低价的油,具体策略如下。
首先处理数据,将起点和终点加入dest和price列表,这样可以统一处理,同时设置终点油价为0,这样终点就可以看做是一个普通结点。并记录最大可走距离
m
a
x
L
=
C
∗
D
2
maxL = C*D2
maxL=C∗D2
假设当前位置为nowIndex,依次遍历所有加油站,找到一个油价比当前低的地方
i
i
i(由于终点油价为0,一定可以找到),然后分情况讨论:
- 若
i
i
i处于可达范围
d
e
s
t
[
i
]
<
=
d
e
s
t
[
n
o
w
I
n
d
e
x
]
+
m
a
x
L
dest[i]<=dest[nowIndex]+maxL
dest[i]<=dest[nowIndex]+maxL,则直接开到
i
i
i位置即可。更新
n
o
w
I
n
d
e
x
nowIndex
nowIndex
为 i i i,并令 c o s t = c o s t + ( d e s t [ i ] − d e s t [ n o w I n d e x ] ) / D 2 ∗ p r i c e [ n o w I n d e x ] ( 正 好 开 到 i 的 价 格 ) cost = cost + (dest[i]-dest[nowIndex])/D2*price[nowIndex] (正好开到i的价格) cost=cost+(dest[i]−dest[nowIndex])/D2∗price[nowIndex](正好开到i的价格) - 若 i i i不在可达范围,则考虑中转加油站,在 [ n o w I n d e x + 1 , i − 1 ] [nowIndex+1,i-1] [nowIndex+1,i−1]范围内找到一个加油站加满油可以开到 i i i。注意,这个加油站一定存在,因为我们先检查问题是否有解。寻找规则如下:在 [ n o w I n d e x + 1 , i − 1 ] [nowIndex+1,i-1] [nowIndex+1,i−1]找油价最低的加油站 m i n I n d e x minIndex minIndex,若 m i n I n d e x minIndex minIndex 可达 i i i则令 n o w I n d e x = i nowIndex=i nowIndex=i并令cost增加上开到i的费用;若minIndex$ 不可达 i i i则令 n o w I n d e x = m i n I n d e x nowIndex=minIndex nowIndex=minIndex并令cost加上补满油的费用
代码
def getMin():
D1, C, D2, P, N = map(float, input().strip().split())
N = int(N)
price = []
dest = []
for i in range(0, N):
l, p = map(float, input().strip().split())
dest.append(l)
price.append(p)
# 将首位添加进数据表,这样可以统一处理
dest.insert(0, 0)
dest.append(D1)
price.insert(0, P)
price.append(0)
# 添加了两个数据
N = N+2
# 检查是否有解 若相邻两站大于maxL则无解
maxL = D2 * C
for i in range(1, N):
if dest[i] - dest[i - 1] > maxL:
print('No Solution')
return
cost = 0
nowIndex = 0
# 在maxL距离内考察,如果油价高于当前则忽略,直到找到一个油价比当前低的地方
# 保证在到达油价低的位置时油箱为空
# 终点油价设置为0,所以一定会走到终点
# 逐个考虑,所以不会遗漏
for i in range(1, N):
# 若在当前可达范围内找到了最近的油价低的一站,直接开过去
if price[i] < price[nowIndex] and dest[i] <= dest[nowIndex] + maxL:
cost = cost + (dest[i] - dest[nowIndex]) / D2 * price[nowIndex]
nowIndex = i
# 找到了低价但无法到达,考虑中转加油站
# 此时显然要在当前位置加满油(可达范围油价均比当前高)
elif price[i] < price[nowIndex] and dest[i] > dest[nowIndex] + maxL:
# nowIndex+1 到 i-1范围油价均比当前高,且i不可达,则一定在当前加油站加满油
cost = cost + C * price[nowIndex]
while True:
# 不断中转直至i可达,选择后续中最低价
minP = price[nowIndex + 1]
minIndex = nowIndex + 1
# 找到后续油价最便宜的地方
for j in range(nowIndex + 1, i):
if minP > price[j]:
minP = price[j]
minIndex = j
# 通过这次中介可达终点,直接计算
if dest[minIndex] + maxL >= dest[i]:
cost += (dest[i] - dest[nowIndex] - maxL) / D2 * price[minIndex]
nowIndex = i
break
else:
# 不可达到终点,补满油继续找后续最低价
cost += (dest[minIndex] - dest[nowIndex]) / D2 * price[minIndex]
nowIndex = minIndex
return cost
print('%.2f'%getMin())