题目链接:https://vijos.org/problems/P1253
描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离d1、汽车油箱的容量c(以升为单位)、每升汽油能行驶的距离d2、出发点每升汽油价格p和沿途油站数n,油站i离出发点的距离d、每升汽油价格p。
计算结果四舍五入至小数点后两位。
如果无法到达目的地,则输出-1。
格式
输入格式
输入共n+1行,第一行为d1,c,d2,p,n,以下n行,每行两个数据,分别表示该油站距出发点的距离d和该油站每升汽油的价格p。两个数据之间用一个空格隔开。
输出格式
一行,输出最少费用。
计算结果四舍五入至小数点后两位。
如果无法到达目的地,则输出-1。
本题练习贪心算法。
分析:走到能走到之内的第一个价格比当前所在点便宜的加油站,如果之后能走到的所有站都比当前点贵 那么就加满油 走到能走到的最便宜的一个站。
如果在这个范围内存在一个加油站j,它的价格pri[j]<pri[i],那么只要把油加到刚好能到达j就可以了;如果在这个范围内不存在这样的加油站,那么就在i加满油,然后走到最便宜的加油站j,如果无法走到j,即最近的加油站dis[j]>dis[i]+c*d2,此时无解。
代码:
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define maxn 102
double d[maxn];//距离
double c;//容量
double d2;//每升油能行驶的距离
double p[maxn];//汽油价格
int n;//加油站个数
double cost;//花费
double rest;//油箱油量剩余
int main()
{
/*#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif*/
double d1;
scanf("%lf %lf %lf %lf %d",&d1,&c,&d2,&p[0],&n);
for(int i=1;i<=n;i++)
{
scanf("%lf %lf",&d[i],&p[i]);
}
d[n+1] = d1;
p[n+1] = 0;
d[0] = 0;
cost = 0;
rest = 0;
int k = 0;
while(k<=n)
{
int j = k;
int flag = 0;
int min = 0;
double need = 0;//在k处需要加多少油
while(d[j+1] - d[k] <= c * d2 && j<=n)
{
j++;
//最近的比当前加油站低的
if(flag == 0 && p[j]<p[k])
{
flag = j;
}
//最便宜的站
if(min == 0 || p[j]<p[min])
{
min = j;
}
}
if(k == j)
{
printf("-1\n");
return 0;
}
//没有比当前加油站价格低的,加满,走到最便宜的一个站
if(flag == 0)
{
need = c - rest;
cost += need * p[k];
rest = c - (d[min] - d[k])/d2;
k = min;
}
//最近的比当前加油站低的
else
{
need = (d[flag] - d[k])/d2 - rest;
if(need < 0)
{
need = 0;
}
cost += need * p[k];
rest = 0;
k = flag;
}
}
printf("%0.2lf\n",cost);
return 0;
}