With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.
Input Specification:
Each input file contains one test case. For each case, the first line contains 4 positive numbers: Cmax (≤ 100), the maximum capacity of the tank; D (≤30000), the distance between Hangzhou and the destination city; Davg (≤20), the average distance per unit gas that the car can run; and N (≤ 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: Pi, the unit gas price, and Di (≤D), the distance between this station and Hangzhou, for i=1,⋯,N. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print The maximum travel distance = X
where X
is the maximum possible distance the car can run, accurate up to 2 decimal places.
Sample Input 1:
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
Sample Output 1:
749.17
Sample Input 2:
50 1300 12 2
7.10 0
7.00 600
Sample Output 2:
The maximum travel distance = 1200.00
分析:
本题使用贪心算法。
步骤如下:
1、在油量加满能到达的最远的范围内,寻找距离当前加油站最近的并且费用比当前小的加油站,加的油量为刚好能到达该费用小的加油站的量。
2、如果找不到这样的加油站,就要在范围内找费用最小的加油站,先在当前站把油加满,再到该费用最小的加油站。(应注意此时的油量不是0)
3、如果在油量加满的情况下找不到任何能到达的加油站,就记录下能到达的最远距离并结束。
测试点2的问题是如果没有一个加油站的距离为0,则无法出发,不能到达终点。
测试点4的问题是考虑不够全面,没有注意到如果在能到达的范围内找不到比当前加油站费用小的加油站时,需要找在该范围内费用最小的加油站,并且还需要注意的是,可能在该最小的加油站加了油之后已经可以到达终点了(即在寻找的过程中已经可以到达终点了),就无需在从该最小加油站出发找更小费用的加油站,要加的油也是刚好能到达终点的量。
下面给出几个测试用例,特别感谢 怪兽不吃人 和 m0_64218410 曾在评论区提供的测试用例。
//input1
4 8 1 6
6 0
5 3
6 4
7 5
8 6
9 7
//output1
44.00
//input2
3 4 1 3
1 0
2 1
100 2
//output2
5.00
//input3
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 100
7.20 200
7.50 400
7.30 1000
6.85 300
//output3
The maximum travel distance = 0.00
代码:
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cmath>
#include <algorithm>
using namespace std;
struct station{
double Pi;
double Di;
}s[30005];
bool cmp(station a,station b){
return a.Di<b.Di;
}
int main(){
double cmax;
double D,Dm;
double Davg;
int N;
double sum=0;
cin>>cmax>>D>>Davg>>N;
Dm=D;
for(int i=0;i<N;i++){
cin>>s[i].Pi>>s[i].Di;
}
sort(s,s+N,cmp);
double longdis=Davg*cmax;
int i=0;
double ddis=0;//上一次加的油还能走多远
while(D>0&&i!=N&&s[0].Di==0){
int t=i;
if(i!=N-1){//确保i不是最后一位
bool flag=false;//判断是不是可以找到比自己小的
int j=i+1;
int mmin=j;
for(j;j<N;j++){
if(s[j].Di-s[i].Di<=longdis){
if(s[j].Pi<s[i].Pi){//找到比自己小的
flag=true;
break;
}else{
if(s[mmin].Pi>s[j].Pi)//如果在自己所能到达的范围内没有比自己小的,就找该范围里最小的
mmin=j;
}
}else{
break;//找不到比自己小的
}
}
if(flag==true){//j要比i小
sum+=s[i].Pi*(s[j].Di-s[i].Di-ddis)*1.0/Davg;//把之前的油加到刚好能到达该处
D-=s[j].Di-s[i].Di;
ddis=0;
i=j;//车子从新的加油站出发
}else{//没找到比自己小的,就先到能到达的范围内的最小的加油站
sum+=s[i].Pi*min(longdis-ddis,D-ddis)*1.0/Davg;//在路途中可能就直接到达终点了
ddis=longdis+s[i].Di-s[mmin].Di;
D-=s[mmin].Di-s[i].Di;
if(D-ddis<=0){//用该站的油可以直接到达终点
D-=ddis;
break;
}
i=mmin;//车子从新的加油站出发
}
}else if(i==N-1&&s[i].Di-s[i-1].Di<=longdis){//如果可以到达最后一个加油站
sum+=D*s[i].Pi*1.0/Davg;
D-=longdis;
break;
}
}
if(D>0)
cout<<"The maximum travel distance = "<<fixed<<setprecision(2)<<(Dm-D)*1.0;
else
cout<<fixed<<setprecision(2)<<sum;
}