贪心之旅行家的预算(详细分析)

题目描述

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

算法分析

这一题是一道很典型的贪心题,但是很难寻找到最佳贪心策略。
这里的关键是加油站,因为加油站关系到钱的多少。抓住加油站,再思考如何加油最少

而要总的消费小,那我们每次加油都需要考虑油价尽可能便宜的加油站加油,那么需要在当前的位置下,假如加满油,看看能经过多少个加油站,然后进行判断,那么可以分成三种情况来做

1、首先考虑如果**加满油都不能到达下一个加油站**,则肯定无法到达目的地,
   则输出"No Solution"
2、在当前加满油后能到达的所有加油站中比较油价,假如当前位置的油价最低,那么一定要
   加满油,然后开到下一个加油站在再次进行比较选择
3、在当前加满油后能到达的所有加油站中比较油价,假如出现了更便宜的加油站,那么只需要
   加的油够刚好到达那一个加油站即可

代码

#include<algorithm>
#include<cstdio>
using namespace std;
const int M=100000005;
struct station{
	double di,pi;
}a[M];
double kio,ans,oil;
bool flag;
int main(){
	double d1,c,d2,p;
	int n;
	scanf("%lf%lf%lf%lf%d",&d1,&c,&d2,&p,&n);
	a[0].di=0,a[0].pi=p,a[n+1].di=d1;
	a[n+1].pi=0,kio=c*d2;
	for(int i=1;i<=n;i++){
		int num;
		scanf("%d %lf %lf",&num,&a[i].di,&a[i].pi);
		if(a[i].di-a[i-1].di>kio)
			flag=true;
	}
	if(flag==true){
		printf("No Solution!");;
		return 0;
	}
	int i=0,j;
	while(i<=n){  
		i=j;
		for(j=i+1;j<=n+1;j++){ 
			if(a[j].di-a[i].di>kio){ 
				j--;
				break;
			}
			if(a[j].pi<=a[i].pi){ 
				break;
			}
 		}
 		if(a[j].pi<=a[i].pi) { 
			ans+=((a[j].di-a[i].di)/d2-oil)*a[i].pi;
			oil=0;
		}
		else{
			ans+=(c-oil)*a[i].pi;
			oil=c-(a[j].di-a[i].di)/d2;
		}
	}
	printf("%.2lf",ans);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值