题目
PAT 甲级 1033 To Fill or Not to Fill (25分) 贪心
思路
易错点
1 输出精确到小数点后两位,即使起点没有加油站,要输出0.00
2 将终点作为最后一个油价为0的加油站处理,方便处理
题解
#include <iostream>
#include <vector>
#include <cstring>
#include <unordered_map>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 510;
const int INF = 0x7fffffff;
struct station {
double p; //每单位汽油价格
double d; //离起始地点距离
station() {
p=0;
d=0;
}
} st[maxn];
bool cmp(station s1,station s2) {
return s1.d<s2.d;
}
int main(int argc,char * argv[]) {
// 1 接收数据
// Cmax油箱容量;
// D起点到终点距离;
// Davg每单位汽油行驶距离
int n; //n 加油站数量
double Cmax,D,Davg;
scanf("%lf%lf%lf%d",&Cmax,&D,&Davg,&n);
for(int i=0; i<n; i++) {
scanf("%lf%lf",&st[i].p,&st[i].d);
}
// 设置终点为哨兵
st[n].p=0;
st[n].d=D;
// 2 按照与起始点距离排序,从小到大
sort(st,st+n,cmp);
// 3 贪心寻找最优解
// 题目已知起始油箱为0,所以起点一定要有一个油站
if(st[0].d!=0) {
printf("The maximum travel distance = 0.00\n");
return 0;
}
int now = 0; //当前站编号
double ans = 0;// 总花费
double nowTank = 0;//当前剩余油量
double MAX=Cmax*Davg; //满油最大行驶距离
while(now<n) {
// 1 求当前站到达范围内(满油行驶距离),第一个油价低于当前站油价的站
// 若找不到,就求出可达范围内最低油价的站
int k=-1;
double priceMin = INF;
for(int i=now+1; i<=n&&st[i].d-st[now].d<=MAX; i++) {
if(st[i].p<priceMin) {
priceMin=st[i].p;
k=i;
if(priceMin<st[now].p) {
break; //已找到比可达范围内,比当前站油价更低的站
}
}
}
if(k==-1)break; //可达范围内没有加油站,旅程失败
double need = (st[k].d-st[now].d)/Davg; //从当前站到k站需要的油量
if(priceMin<st[now].p) {
// 如果可达范围内,有比当前油价更低的油站,只需要添加到达该站的油量
if(nowTank<need) {
ans+=(need-nowTank)*st[now].p;
nowTank=0; //到达k站,汽油余量为0;
} else {
nowTank-=need; //到达k站,减掉消耗的汽油量
}
} else {
ans+=(Cmax-nowTank)*st[now].p;
nowTank=Cmax-need; //到达k站剩余汽油量
}
now = k;
}
if(now==n) {
//能到达终点
printf("%.2f\n",ans);
} else {
printf("The maximum travel distance = %.2f\n",st[now].d+MAX);
}
return 0;
}