pat甲级1033 To Fill or Not to Fill(25 分)

题目链接
分析:贪心算法。
贪心思想:
0.寻找比自己距离远的,到能够到达的最大距离之间的加油站,看他们的油价。如果找到了更低价格的油价,就加油到刚好能到达那个加油站的距离的油,然后去那个更低价格的加油站(有更低的我一分都不想多花在别的距离上,只加到刚好满足更低价格的加油站的距离就行,那样以后的路程我就可以以更低的价格行驶啦)
1.如果找不到更低的,就找尽可能低的油价的加油站,在当前加油站加满油之后过去。因为想要让路程上使用的尽可能是低价的油,既然没有比当前更低价格的了,就让油箱加到最大值,这样能保证利益最大化,保证最大的距离使用的是便宜的油。

#include<bits/stdc++.h>
using namespace std;
double cMax,D,dAvg;
int n;
struct station{
	double price;
	double dis;
}s[505];
bool cmp(station x,station y){
	return x.dis<y.dis;
}
int main(){
	cin>>cMax>>D>>dAvg>>n;
	for(int i=0;i<n;i++){
		cin>>s[i].price>>s[i].dis;
	}
	s[n].price=0;
	s[n].dis=D;
	sort(s,s+n+1,cmp);
	if(s[0].dis!=0){//如果起始位置没有加油站 
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	int cur=0;//当前加油站编号
	double curTank=0;//当前剩余油量 
	double minPrice;//最小油费价格 
	int minInd=0; //最小油费加油站编号
	double totalPrice=0;//总共花费 
	while(s[cur].dis<D){
		int maxRun=cMax*dAvg+s[cur].dis;//当前地点加满油能够到达的最大范围
		minPrice=0x3fffffff;
		for(int i=cur+1;i<=n&&s[i].dis<=maxRun;i++){
			if(s[i].dis==D){//能够到终点直接到终点 
				minInd=i;
				minPrice=0;
			}else{//寻找能够到达范围内最小油价的加油站
				if(s[i].price<s[cur].price){//找到了maxRun范围内比当前加油站油价更低的最近一个加油站 
					minInd=i;
					minPrice=s[i].price;
					break;
				}else if(minPrice>s[i].price){//没有找到更低油价的,找maxRun内最低油价的加油站 
					minPrice=s[i].price;
					minInd=i;
				} 
			}
		}
		if(minPrice==0x3fffffff){//maxRun内没有加油站,加满油最后一搏! 
			printf("The maximum travel distance = %.2lf\n",cMax*dAvg+s[cur].dis); 
			return 0;
		}
		if(minPrice>=s[cur].price){//maxRun范围内的都比当前加油站油费高,
		//在当前加油站加满油,并到maxRun范围内最低油价的加油站 
			totalPrice+=s[cur].price*(cMax-curTank);
			curTank=cMax-(s[minInd].dis-s[cur].dis)/dAvg;
			cur=minInd;
		}else{//能够在maxRun范围内找到更低油价的加油站,加到能够刚好到达该加油站的油就行
		 	totalPrice+=s[cur].price*((s[minInd].dis-s[cur].dis)/dAvg-curTank); 
			curTank=0;
			cur=minInd;
		}
	}
	printf("%.2lf\n",totalPrice);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值