返回目录
题意
已知起点与终点的距离为D,油箱的最大油量为Cmax,单位汽油能够支持前进Davg.给定N个加油站的单位油价和离起点的距离(所有加油站都在一条线上),汽车初始时刻处于起点位置,油箱为空,且可以在任意加油站购买任意量的汽油(前提是不超过油箱容量),求从起点到终点的最小花费。如果无法到达终点,则输出能够行驶的最远距离。
样例(可复制)
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
样例输出
749.17
注意点
- 本题贪心策略如下:①寻找距离当前加油站最近的油价低于当前油价的加油站(记为k),加恰好能够到达加油站k的油,然后前往加油站k (即优先前往更低油价的加油站)。
②如果找不到油价低于当前油价的加油站,则寻找油价最低的加油站,在当前加油站加满油,然后前往加油站k ( 即在没有更低油价的加油站时,前往油价尽可能低的加油站)。
③如果在满油状态下都找不到能到达的加油站,则最远能到达的距离为当前加油站的距离加上满油状态下能前进的距离,结束算法( 即没有加油站可以到达时结束算法)。
上面的策略当满足条件③、或者到达加油站n (即终点)时结束。 - 为了解题方便,设定了一个station结构体,之后按照距离给其排序,方便处理
- 注意Cmax,D,Davg,油价和距离都可能为浮点类型
- 起点处没有加油站的最远距离为0,不是当前位置+Cmax*Davg,没有区分开的话有个测试点过不了
- 经测试,本题不会出现两个相同位置的加油站
#include <bits/stdc++.h>
using namespace std;
struct station{
double price,pos;
}sta[510];
bool cmp(station a,station b){
return a.pos<b.pos;
}
int main(){
double Cmax,D,Davg;;
int n;
cin>>Cmax>>D>>Davg>>n;
for(int i=0;i<n;i++)scanf("%lf%lf",&sta[i].price,&sta[i].pos);
sta[n].price=0;sta[n].pos=D;
sort(sta,sta+n,cmp);
if(sta[0].pos!=0){
cout<<"The maximum travel distance = 0.00";return 0;
}
double gas=0,free=0,dis=Cmax*Davg;//当前油箱的油量,总共花费的钱,当前能走的最远距离
int now=0;//当前标号
while(now!=n){
int maxget=0;//最远能到的加油站标号
for(int i=0;i<n+1;i++){//找到最远能到的加油站标号
if(sta[now].pos+dis>=sta[i].pos)maxget=i;
}
if(maxget==now)break; //最远标号是当前标号
int minprice=now+1;
for(int i=now+1;i<=maxget;i++){//找到可去的加油站中最合适的那个
if(sta[i].price<sta[now].price){
minprice=i;break;
}
if(sta[i].price<sta[minprice].price)minprice=i;
}
if(sta[minprice].price<sta[now].price){//如果有更便宜的加油站
double needgas=(sta[minprice].pos-sta[now].pos)/Davg;
if(gas>=needgas){
gas-=needgas;
}else{
free+=(needgas-gas)*sta[now].price;
gas=0;
}
}else{//如果当前价格更便宜
free+=(Cmax-gas)*sta[now].price;
gas=Cmax-(sta[minprice].pos-sta[now].pos)/Davg;
}
now=minprice;
}
if(now!=n)printf("The maximum travel distance = %.2f",sta[now].pos+dis);
else printf("%.2f",free);
return 0;
}