旅行家的预算
时间限制: 1 Sec 内存限制: 64 MB
题目描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(0<=N<=100),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,……N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No solution”。
输入
第1行:5个空格分开的数据,分别表示D1 C D2 P N
第2..N+1行:每行3个空格分开的数据,分别表示油站号i, 该油站距出发点的距离Di,该油站每升汽油的价格Pi
输出
第1行:一个数据,表示最少费用
样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
275.6 11.9 27.4 2.8 2
1 102.0 2.9
2 220.0 2.2
样例输出
26.95
【解】
1,因为要到达目的地且油箱容量和每升油可行路程一定,所以当路途中的两个加油站间路程大于油箱最大可行路程时,无解。(No solution)
2,在已经行驶过的加油站中,选择价格最优者(且剩余可加油量不为0)尽量加满(同一价格可加油量最多为油箱容量),并维护当前价格的剩余可加油量。(优先队列维护)
3,在当前价格最优的剩余可加油量不足以支持其到达下一个加油站点时,先加满当前价格的剩余可加油量(并应去掉此价格的可选方案),再选择剩下价格中的最优,直到油箱中的油足够支持其走到下一加油站点。
4,到达新的加油站点时,因为其价格可能影响后面路程油价的方案选择,所以应将其生成一种新的可选方案以备选用,并维护其油价及其可加油量(初始时为油箱容量)
第一份(20160701)
#include<cstdio>//优先队列:加油站油价低为最优
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
struct node{
int num;
double jrn,unit,all;
bool operator>(const node &a)const{
return unit>a.unit;
}
}gas[110];
bool cmp(node a,node b){
return a.jrn<b.jrn;
}
priority_queue<node,vector<node>,greater<node> >q;
int main(){
int n,i;
double d1,c,d2,ans=0.0;
scanf("%lf%lf%lf%lf%d",&d1,&c,&d2,&gas[0].unit,&n);
for(i=1;i<=n;i++){
scanf("%d%lf%lf",&gas[i].num,&gas[i].jrn,&gas[i].unit);
gas[i].all=c;
}
sort(gas,gas+n+1,cmp);
gas[0].jrn=0.0;gas[0].all=c;//初始化
gas[n+1].unit=0x3f3f3f3f;gas[n+1].jrn=d1;
n++;//终点路程需加入
q.push(gas[0]);//起点看作一个加油站先行放入
node last;
double now,al;//now:从上一个加油站点为走到当前站点的所需油量,al:已加油需要花费的价格
for(i=1,al=0.0;i<=n;i++,al=0.0){
now=(gas[i].jrn-gas[i-1].jrn)/d2;
if(now>c){printf("No solution\n");return 0;}
while(!q.empty()){
last=q.top();
if(now==0)break;
if(last.all>now){
last.all-=now;
al+=now*last.unit;
now=0;
q.pop();
q.push(last);
break;
}
else if(last.all==now){
al+=now*last.unit;
q.pop();
break;
}
else {
now-=last.all;
al+=last.all*last.unit;
q.pop();
}
}
ans+=al;
q.push(gas[i]);
}
printf("%.2lf\n",ans);
}
第二份(20200116)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int Maxn = 500 + 5;
int N;
double d1, c, d2, p0, d, ans, vlm;
pair<double, double>G[Maxn];
int main(){
scanf("%lf%lf%lf%lf%d", &d1, &c, &d2, &p0, &N);
d = c*d2;
for(int i = 1; i <= N; ++ i)
scanf("%lf%lf", &G[i].first, &G[i].second);
G[0] = make_pair(0.0, p0);
sort(G+1, G+1+N);
++ N;
G[N] = make_pair(d1, 0.0);
for(int i = 0; i < N;){
int p = i+1;
for(int j = i+1; j <= N && G[j].first <= G[i].first+d; ++ j)
if(G[j].second < G[i].second){
p = j;
break;
}
if(G[p].first > G[i].first + d){
puts("No Solution");
return 0;
}
if(G[p].second >= G[i].second){
ans += G[i].second*(c-vlm);
vlm = c-(G[p].first-G[i].first)/d2;
i = p;
}
else{
if(vlm*d2 >= G[p].first - G[i].first)
vlm -= (G[p].first - G[i].first)/d2;
else
ans += G[i].second*(G[p].first-G[i].first-vlm*d2)/d2, vlm = 0.0;
i = p;
}
}
printf("%.2lf\n", ans);
return 0;
}