Problem C: To Fill or Not to Fill
题目大意:
首先,我们通过输入可以获得:油箱的最大容量(Cmax),目的地距离杭州的距离(D),一单位的油可以行驶的距离(Davg),加油站的个数(N)。以及每个加油站对应的油价和距离杭州的距离。 我们要做的就是判断该车能否到达目的地,要是可以到达目的地,就输出达到目的地所需要最少的油费,否则输出该车能行驶的最远距离。
思路
一、首先判断该车能否到达目的地,分别考虑两种情况: (1)起点根本就没有加油站,汽车无法启动 (2)中途两个加油站之间的距离大于加满油后汽车能够行驶的最大距离。(这里应考虑到当最后一个加油站距离终点的距离大于汽车行驶的最大距离的情况) 二、如果上面的两种情况都没有发生,我们就需要计算该车行驶到终点需要花费的最少油费。这道题考的是贪心算法,即在每一次选着加油站的时候,都选着最优的情况。 (1)这道题非常巧妙的一个做法就是将终点也视为一个加油站(距离为D,油价为0)。这样子做,许多情况都不用单独考虑了,比如刚刚提到的最后一个加油站到终点的距离。 (2)然后,再将加油站类型的数组按照加油站距离杭州的距离,由小到大排序。这样就相当于将所有的加油站按序放在了一条的笔直的公路上,再来考虑问题就非常的直观。 (3)然后,我们从起点开始,每次去选着最优的加油站,需要考虑的情况如下:
- 我们每次考虑的加油站仅限于汽车加满油时,可行驶范围内的加油站。
- 情况一:从当前站往后遍历,如果有一加油站的油价低于当前站的油价,就直接前往。注意:只需要比当前加油站的油价低即可,不需要去找最低的。
- 情况二:如果在范围内,没有一家加油站的油价比当前油价低。则寻找范围内油价最低的,要是有多个油价最低的,则选择离当前站最近的站即可。
(4)(3)中已经实现每次寻找最优的加油站了。接下来我们计算油费。
- 要是下一个站的油价比当前的站低,我们先要考虑剩余的油能否到达下一个站,能到达则不加油,否则,我们需要加油,油量只需要满足刚好到达下一站即可。
- 要是下一个站的油价比当前的站高或者一样,我们则需要在当前站加满油,前往下一站即可。
C++代码实现(AC)
#include<cstdio>
#include<algorithm>
using namespace std;
struct Station{
double price;
double distance;
}station[510];
bool cmp(Station a, Station b){
return a.distance < b.distance;
}
int main(){
freopen("input.txt", "r", stdin);
double Cmax;
double D;
double Davg;
int N;
double X;
while(scanf("%lf%lf%lf%d", &Cmax, &D, &Davg, &N) != EOF){
double ans = 0;
for(int i = 0; i < N; i++){
scanf("%lf%lf", &station[i].price, &station[i].distance);
}
station[N].distance = D;
station[N].price = 0.00;
sort(station, station+N+1, cmp);
double maxDistance = Cmax * Davg;
if(station[0].distance > 0){
X = 0;
printf("The maximum travel distance = %.2f\n", X);
return 0;
}else{
for(int i = 1; i <= N; i++){
if(station[i].distance - station[i-1].distance > maxDistance){
X = station[i-1].distance + maxDistance;
printf("The maximum travel distance = %.2f\n", X);
return 0;
}
}
}
double curDistance = 0;
double remainGas = 0.0;
int curStation = 0;
int nextStation = 0;
while(curDistance < D){
for(int i = curStation+1; i <= N; i++){
if(station[i].distance <= curDistance + maxDistance){
nextStation = i;
}
}
for(int i = curStation+1; i <= nextStation; i++){
if(station[i].price < station[curStation].price){
nextStation = i;
break;
}
}
if(station[nextStation].price >= station[curStation].price){
int temp = nextStation;
double minPrice = station[curStation+1].price;
nextStation = curStation + 1;
for(int i = curStation+2; i <= temp; i++){
if(station[i].price < minPrice){
minPrice = station[i].price;
nextStation = i;
}
}
}
if(station[nextStation].price < station[curStation].price){
if (remainGas*Davg >= station[nextStation].distance - curDistance) {
remainGas = remainGas - (station[nextStation].distance - curDistance) / Davg;
}else {
ans = ans + ((station[nextStation].distance - curDistance) / Davg - remainGas) * station[curStation].price;
remainGas = 0;
}
}else{
ans = ans + (Cmax - remainGas) * station[curStation].price;
remainGas = Cmax - (station[nextStation].distance - curDistance) / Davg;
}
curDistance = station[nextStation].distance;
curStation = nextStation;
}
printf("%.2f\n", ans);
}
return 0;
}
|