题解:P1016 [NOIP 1999 普及组/提高组] 旅行家的预算
Morning_field · · 题解
P1016
大意
一个人开车从一个城市去另一个城市,出发时油箱是空的。已知两个城市距离、油箱容量、每升油能跑多远、起点的油价,还有沿途
问:怎么加油最省钱,算出最少要花多少钱。如果根本开不到终点,就输出 No Solution。
思路
贪心,能省就省。
站在当前加油站,往前看:
前面有更便宜的油:就加刚好够开到那的油,到那再加便宜的。
前面都比这贵:那就在这把油加满,然后开到前面最便宜的那个站再加油。
重复上面的,直到开到终点,中途判断一下会不会到不了终点。
具体实现看代码。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=507;
const double inf=0x3f3f3f3f;
struct node{
double l,p;
}a[maxn];
bool cmp(node x,node y){
return x.l < y.l;
}
int main(){
double s,c,l,p0;
int n;
cin>>s>>c>>l>>p0>>n;
a[0].l=0;
a[0].p=p0;
for(int i=1;i<=n;i++){
cin>>a[i].l>>a[i].p;
}
a[n+1].l=s,a[n+1].p=0;
sort(a,a+n+2,cmp);
double mr=c*l; //满油能跑多远
double nr=0; //当前油量
double cost=0; //花了几个钱
int now=0; //当前在第几个站
bool ok=1;//是否能到终点
if(s==0.00){
cout<<"0.00";//特判
return 0;
}
//找第一个比当前便宜的油站:
while(now <= n){
int nt=-1;
for(int i=now+1;i<=n+1;i++){
double d=a[i].l-a[now].l;
if(d > mr) break;
if(a[i].p < a[now].p){
nt=i;
break;
}
}
//如果找不到更便宜的,就找范围内最便宜的:
if(nt == -1){
double mp=1e18;
for(int i=now+1;i<=n+1;i++){
double d=a[i].l-a[now].l;
if(d > mr) break;
if(a[i].p < mp){
mp=a[i].p;
nt=i;
}
}
}
//一个站都到不了,无解
if(nt==-1){
ok=0;
break;
}
//计算开到下一站需要多少油
double nd=(a[nt].l-a[now].l)/l;
//决定加多少油:
if(a[nt].p < a[now].p){
//1.下一站更便宜 加刚好到下一站的油
if(nr < nd){
cost+=(nd-nr)*a[now].p;
nr=nd;
}
}
//2.下一站更贵 加满
else {
cost+=(c-nr)*a[now].p;
nr=c;
}
nr-=nd;
now=nt;
}
if(!ok) cout<<"No Solution";
else cout<<fixed<<setprecision(2)<<cost;
return 0;
}