PAT A1033加油站问题(较难的贪心算法)

本文介绍了一种算法,用于计算从起点到终点的最经济路线,考虑到油箱容量、汽油效率、加油站位置和价格。通过寻找最低油价的加油站并计算最小花费,确保了全程的最低成本。若无法直达终点,算法还能估算出最大可行距离。

题意:

已知起点到终点的距离为D,油箱的最大油量为Cmax,单位汽油能够前进的距离Davg,加油站的个数N。
给定N个加油站的油价和距离,如果可以到达终点,计算最小花费;如果到达不了,计算能行驶的最远距离。

思路:

对于当前结点(加油站):
1.在“可到达的范围”内,寻找油价比当前加油站低的“第一个”加油站。
计算花费:只要足够从当前站到目标站的油量的油。
如果当前油量不足,在当前站购买足够油量。
如果油量够,到达目标战之后减去需要油量。
2.如果所有可到达的加油站的油价都没有当前油价低,则加满油箱,寻找在可到达的加油站的油价最低的加油站进行加油。
计算花费:在当前站加满油箱,到达下一站的时候剩余油量为满油量-需要的油量。

找到目标站之后再对目标站进行循环。

对于每一个结点进行上诉循环,找到每一个结点的最少花费,最后就能得出从起点到终点的最少花费。

如果最后结束循环时当前站为终点站,则输出最少花费
如果不是,则输出最远距离。

坑点:
1.如果第一站的距离不为0,则根本不能出发,最远距离为0.00
2.Cmax、D、Davg,price都有可能是浮点型,不能设置成int
3.带有两位小数,使用%.2f输出

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
struct station{
	double price;   //价格 
	double d;     //距离 
}s[500];
bool cmp(station a,station b){
	 return a.d<b.d;   //按照距离排序 
}
int main(){
	double Cmax,D,Davg;
	int N;
	scanf("%lf%lf%lf%d\n",&Cmax,&D,&Davg,&N);
	for(int i=0;i<N;i++){
		scanf("%lf %lf\n",&s[i].price,&s[i].d);
	}
	s[N].price=0;  //数组最后存放终点,价格为0 
	s[N].d=D;  //距离为D 
	sort(s,s+N,cmp);   //按距离从大到小排序 
	if(s[0].d!=0){   //如果第一个加油站的距离不是0,由于油箱里面没有油,所以不能前进 
		printf("The maximum travel distance = 0.00\n");
	}else{
		int now=0;  //当前加油站的编号
		double ans=0,nowTank=0,MAX=Davg*Cmax;  //ans为总花费,nowTank为当前油量,MAX是满油能够行驶的最大距离 
		while(now<N){  //每次循环找出下一个应该去的加油站 
		//选出从当前油站能"到达范围内"的"第一个"油价低于当前油价的加油站
			//如果找不到低于当前油价的加油站,则选择价格最低的那个 
			int k=-1;    //最低价的加油站的编号 
			double priceMin=10000000;   //最低油价 
			for(int i=now+1;i<=N&&s[i].d-s[now].d<=MAX;i++){     
				if(s[i].price<priceMin){    //如果当前的油价比最低油价低 
					priceMin=s[i].price;  //则更新最低油价 
					k=i;              
					if(priceMin<s[now].price){  //如果找到第一个油价低于当前油价的加油站,直接中断循环,开始计算花费 
						break;                  //如果不符合这个条件,则会寻找到可到达的加油站中的最低价   
					}     //可以得到下一个目标站k 
				}
			}
			if(k == -1)  break; //找不到符合条件的,退出循环 
			//下面为能找到的可到达的加油站k,计算费用   
			double need=(s[k].d-s[now].d)/Davg;   //到达k加油站所需要的油量 
			if(priceMin<s[now].price){   //如果加油站的油价低于当前油价 
			//只要买足够到达加油站k的油 
				if(nowTank<need){      //如果油量不足 
					ans+=(need-nowTank)*s[now].price;  //在当前站补足油量 
					nowTank=0;//到达加油站k之后油量全部耗尽 
				}else nowTank-=need;   //如果油量充足,直接到达加油站k 
			}else { //如果加油站k的油价高于当前油价 
				ans+=(Cmax-nowTank)*s[now].price;   //将油箱加满 
				nowTank=Cmax-need;  //到达k站之后油箱的油量为Cmax-need 
			}
			now=k;  //到达加油站k,进入下一个循环 
		} 
		if(now==N){   //能到达终点 
			printf("%.2f\n",ans);
		}else {   //不能到达终点 
			printf("The maximum travel distance = %.2f\n",s[now].d+MAX);
		}
	}
	return 0;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值