[NOIP1999]旅行家的预算

题目描述

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离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行:一个数据,表示最少费用

样例输入

 (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

275.6 11.9 27.4 2.8 2
1 102.0 2.9
2 220.0 2.2

样例输出

26.95
分析:
按Di从小到大排序,for循环依次压如优先队列,如果把队列里比当前的加油站贵的换成当前加油站的油;
P.S:加油时不加ans,用油时在加相应价格。
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
struct node{
	double a,b,c;
	node(){};
	node(double x,double y,double z){
		a=x;b=y;c=z;
	}
	bool operator<(const node &x)const {
		return b>x.b;
	}
};
struct node2{
	double b,c;
	node2(){};
	node2(double x,double y){
		b=x;c=y;
	}
}station[110];

bool cmp(node2 x,node2 y){
	return x.b<y.b;
}
double d1,c,d2,p;
int n;
priority_queue<node>q;
priority_queue<node>q1;
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int i;
	double fuel=0,ans=0,a;
    scanf("%lf %lf %lf %lf %d",&d1,&c,&d2,&p,&n);
	for(i=1;i<=n;i++)
		scanf("%lf %lf %lf",&a,&station[i].b,&station[i].c);
	sort(station+1,station+n+1,cmp);
	station[0]=node2(0.0,p);
	station[n+1]=node2(d1,0.0);
	for(i=0;i<=n;i++){
		if(station[i+1].b-station[i].b>c*d2){
			printf("No solution\n");
			return 0;
		}
		while(!q.empty()){
			if(q.top().b>station[i].c){
				break ;
			}
			q1.push(q.top());
			fuel-=q.top().c;
			q.pop();
		}
		while(!q.empty()){
			fuel-=q.top().c;
			q.pop();
		}
		while(!q1.empty()){
			fuel+=q1.top().c;
			q.push(q1.top());
			q1.pop();
		}
		q.push(node(i,station[i].c,c-fuel));
		fuel=c;
		double s=station[i+1].b;
		while(!q.empty()){
			node t=q.top(),e;
			e=t;
			q.pop();
			t.c-=(s-station[i].b)/d2;
			if(t.c>0){
				ans+=(e.c-t.c)*t.b;
				fuel-=e.c-t.c;
				q.push(t);
				break ;
			}
			else if(t.c==0){
				ans+=e.c*t.b;
				fuel-=e.c;
				break ;
			}
			s-=e.c*d2;
			fuel-=e.c;
			ans+=e.c*t.b;
		}
	}
	printf("%.2lf\n",ans);
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值