问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,……N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入格式 第一行为4个实数D1、C、D2、P与一个非负整数N;
接下来N行,每行两个实数Di、Pi。
输出格式 如果可以到达目的地,输出一个实数(四舍五入至小数点后两位),表示最小费用;否则输出“No Solution”(不含引号)。
样例输入 275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
样例输出
26.95
思路:是找在最大行驶距离内寻找比当前便宜的加油站,然后判断是否能一次到达,不能的话先加满,然后一个一个判断直到剩下的油量不足到下一个加油站就加油,加适量。
于是有以下2 situations: 1.这个站点j 就是pos 再细分两种情况: 1.从pos就可以走到终点 于是我们把油加到刚好到达终点即可 cost += ((d[i] - d[pos]) / d2 - remain)*p[pos];就得到了最后答案。 remain是当前剩余的油 2.从pos不能一把走到终点 于是,从当前位置走,走到哪里加油都不够在pos这里加油划算。 所以加满。 2.这个站点j 是在pos后面的某个站点 也有两种情况 1.当前剩余的油remain不够走到j 于是我们,把油加来刚好能够走到j就行了。(因为j这里好好便宜!) 2.剩余的油remain足够,直接开过去就行了。
########具体操作见如下代码
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
double d[10000], p[10000]; //出发点每升汽油的价格p
int main()
{
ios::sync_with_stdio(false); //取消cin在stdin上的同步,增加cin的读取效率
double d1, c, d2;
int n; //沿途油站数目
cin >> d1 >> c >> d2 >> p[0] >> n;
d[n + 1] = d1; //第n个油站后即为最后的站点
for (int i = 1; i <= n; i++) //输入每一个油站离出发点的距离以及每个站点汽油的价格
{
cin >> d[i] >> p[i];
}
int pos = 0;
double remain = 0, cost = 0;
do
{
bool found = false; //判定能不能到达
for (int i = pos + 1; i <= n + 1 && d[i] <= d[pos] + c*d2; i++) //循环判断加满油能不能到达下一个加油站
{
if (p[i] < p[pos]) //判断下个站点汽油的价格是不是比这个pos站点汽油的价格小
{
if (d[pos] + remain*d2 >= d[i]) //若是剩余的油足够,刚好开过去
{
remain -= (d[i] - d[pos]) / d2; //剩余的油减少,减少量就是从一个站点到下一个站点用到的油
}
else //剩余的油不够
{
cost += ((d[i] - d[pos]) / d2 - remain)*p[pos]; //还需要加的油花费的价钱,不用加满
remain = 0; //到达下一个站点恰好没油了,所以剩余汽油量清0
}
pos = i;
found = true;
break;
}
}
if (!found)
{
cost += (c - remain)*p[pos]; //不能到达前花费了多少钱
remain = c - (d[pos + 1] - d[pos]) / d2; //还剩多少油
if (remain >= 0) pos++; //小于0,油根本不够到达下一个站点,大于0,代表可以去下一个加油站
else
{
cout << "No Solution";
return 0;
}
}
} while (pos <= n); //循环条件:没到达终点
cout.setf(ios::fixed); //以定点形式显示浮点数
cout << setprecision(2) << cost;
}