题目大意
一辆车有容量为 C C C 的油箱,每单位油可以前进 D 2 D2 D2 距离。现想去 D 1 D1 D1 外的终点,笔直的沿途有 n n n 个加油站,每个加油站位于距起点 d i d_i di 处,出售单价 p i p_i pi 的油。起点也有加油站,油箱初始为空。试问车是否能到达终点?若能,求最小加油总花费。
解题思路
不难想到贪心。
尽量在油价低的地方加油,在不浪费的前提下尽量加满油。
注意浮点数处理和每次的加油量计算的细节。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int MAXN=10;
const double delta=0.0000001;
double d1, c, d2;
int n;
int id[MAXN];
struct station{
double d, p;
station(){
d=p=0.0;
}
}sta[MAXN];
double end[MAXN];
//designed for the doubles
double mymin (const double a, const double b){
if (a-b<delta) return a;
return b;
}
int cmp (const int a, const int b){
return ((sta[a].p-sta[b].p)<delta)?1:0;
}
int main (){
scanf ("%lf%lf%lf%lf%d\n", &d1, &c, &d2, &sta[0].p, &n);
sta[n+1].d=d1; id[0]=0;
for (int i=1; i<=n; ++i){
scanf ("%lf%lf", &sta[i].d, &sta[i].p);
id[i]=i;
}
std::sort (id, id+n+1, cmp);
double ans=0.0, maxs=c*d2;
for (int i=0; i<=n; ++i)
end[i]=sta[i].d;
for (int i=0; i<=n; ++i){
int t=id[i];
double dis=sta[t+1].d-end[t];
if (dis<delta) continue; //凭上次加过的油可以直接到达下一加油站
//本次加满油也到不了下个加油站
if (sta[t+1].d-sta[t].d-maxs>delta){
printf ("No Solution");
exit (0);
}
//本次加油后最多前进的路程
double remain=maxs;
int now=t;
while (now<=n&&remain>delta){
if (end[now]-sta[now+1].d<delta){
//有需要才加油
double cnt=mymin (remain, sta[now+1].d-end[now]);
ans+=cnt/d2*sta[t].p;
end[now]+=cnt;
remain-=cnt;
}else break;
++now;
}
}
printf ("%.2lf", ans);
}