题目描述
在国庆期间,聪聪想从南京出发到常州找他的弟弟笨笨玩。他刚刚考了驾照,妈妈又允许他使用家里的轿车,于是就决定自己开车去。
聪聪从南京的一个加油站出发(这时油箱是空的)。沿途会有很多加油站,聪聪可以在某些加油站进去加油,且不一定每次都要把油箱加满。需要注意的是,每个加油站的费用不一定相同。我们都知道现在的油价非常贵,所以聪聪希望他在路上为汽油花费的钱尽可能少。现在请你帮助他计算最小的花费。
输入格式
输入文件trip.in包含N+2行。
第1行只包含一个正整数N,表示沿途的加油站的数量(包含出发点)。
第2行包含3个实数D、C、d0,分别表示南京与常州的距离、汽车油箱的最大容量(单位是升)、每升汽油所能行驶的距离。
第3到N+2行,每行包含两个实数,其中第i+2行的两个数di、pi分别表示第i个加油站与南京的距离、该加油站每升油的费用。输入数据保证di随着i的增大是单调递增的,且d1=0。
输出格式
如果聪聪无法到达目的地,则输出“Poor Congcong”,否则输出一个实数,表示最小花费,结果保留2位小数。
输入样例 复制
3
275.6 11.9 27.4
0.0 2.8
102.0 2.9
220.0 2.2
输出样例 复制
26.95
数据范围与提示
对于40%的数据,n≤10。
对于60%的数据,n≤8000。
对于全部的数据,n≤500000。
前70%的数据都是完全随机生成的。
保证输入数据、所有计算过程的中间结果、输出不超过双精度实型(Double)的范围。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
double d1,c,d2,n,p1,lc,ans,yx;
struct liu{
double d,p;
}a[10005];
int main() {
scanf("%lf%lf%lf%lf%lf",&d1,&c,&d2,&p1,&n);
lc=c*d2;
for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].d,&a[i].p);
double i=0,yq=p1;
while(i<d1) {
double t=i+lc,_min=1e9;
int bh=0;
for(int j=1;j<=n;j++) {//在范围内寻找能省钱且最近的
if(a[j].d>i&&a[j].d<=t&&a[j].d<d1&&a[j].p<yq&&a[j].d<_min) {
bh=j,_min=a[j].d;
}
}
if(bh!=0) ans+=((a[bh].d-i)*yq-yx)/d2,i=a[bh].d,yq=a[bh].p,yx=0;
//剩余油不可能直接使到达
//不能找到,分为能否直接到达终点以及有无后续加油站两方面同时考虑
else {
_min=1e9,bh=0;
for(int j=1;j<=n;j++) {//在范围内寻找最便宜(并不省钱)的加油站
if(a[j].d>i&&a[j].d<=t&&a[j].d<d1&&a[j].p<_min) _min=a[j].p,bh=j;
}
//无后续加油站且无法直接到达终点
if(bh==0&&t<d1) {
printf("No Solution");
return 0;
}
//能直接到达,最划算
if(t>=d1) {
if(yx<(d1-i)/d2) {
ans+=((d1-i)/d2-yx)*yq;
}
break;
}
//不能直接到达但有后续加油站,先加满(省钱),记录剩余油的多少
//加满和到最便宜的地方是关键
else {
ans+=(c-yx)*yq;
yx=c-(a[bh].d-i)/d2;
yq=a[bh].p,i=a[bh].d;
}
}
}
printf("%.2lf",ans);
}