*PS:原来加油是不需要一升一升加的么QWQ
题目描述 Description
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,……N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入描述 Input Description
第一行D1 C D2 P N
之后N行,每行2个数表示离出发点的距离Di和每升汽油的价格Pi
输出描述 Output Description
最消费用,保留2位小数
样例输入 Sample Input
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
样例输出 Sample Output
26.95
数据范围及提示 Data Size & Hint
N<=100
一道贪心题。
刚开始觉得挺简单的,后来发现有油量的限制,QAQ什么鬼啊。。。
然后开始贪心。。。
(我的思想和代码都比较麻烦qwq)
油加进去都是一样的,发现,如果当前的价格“较小”,油量又未满,那就多加点,答案一定不会更差。
问题就是怎么判断当前的价格“较小”。
记一个指针pos表示当前加到了哪个加油站,rest表示当前剩余的油量。
贪心策略:
在pos之后(pos时加满油)最远可到达的加油站中找一个价格最小的。
如果那个价格大于等于pos的价格,就把在pos时加满油箱。
否则就只把油加到刚好能到那个地方,再继续加油。
最后特判一下当前能刚好到终点还需加的油量输出答案就行了。
no solution的情况只需在输入时判断是否有在这个加油站加满油还无法到达下一个加油站的情况qwq。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int N,can,pos,j;
double D1,C,D2,rest,minn,ans;
double D[105],P[105];
int main()
{
scanf("%lf%lf%lf%lf%d",&D1,&C,&D2,&P[0],&N);
P[N+1]=1e9+7;
if(N==0&&D1>C*D2) can=1;
for(int i=1;i<=N;++i)
{
scanf("%lf%lf",&D[i],&P[i]);
double k=D[i]-D[i-1];
if(k>C*D2) can=1; //处理no solution 的情况
}
if(!can)
{
while(pos<=N)
{
minn=P[pos+1],j=pos+1;
for(int i=pos+1;i<=N&&(D[i]-D[pos])<=C*D2;++i)
if(minn>P[i]) minn=P[i],j=i; //找油价最小的一个
double k=(D[j]-D[pos])/D2;
if(minn>=P[pos])
{
if(minn>P[pos]&&(D1-D[pos])<=C*D2) //如果当前加油站后没有油价比他更小的加油站并且在当前加油站加满油可以到达终点,就直接走到终点。
{
k=(D1-D[pos])/D2;
if(rest<k) ans+=(k-rest)*P[pos];
break;
}
ans+=(C-rest)*P[pos]; //加满并走到那个加油站
rest=C-k;
}
else
{
if(rest<k) ans+=(k-rest)*P[pos],rest=0; //刚好走到那里。
else rest-=k;
}
pos=j;
}
printf("%.2f",ans);
}
else printf("No Solution");
return 0;
}