PAT 甲级 1033 To Fill or Not to Fill (25分) 贪心

题目

PAT 甲级 1033 To Fill or Not to Fill (25分) 贪心

思路

题解

易错点

1 输出精确到小数点后两位,即使起点没有加油站,要输出0.00
2 将终点作为最后一个油价为0的加油站处理,方便处理

题解

#include <iostream>
#include <vector>
#include <cstring>
#include <unordered_map>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 510;
const int INF = 0x7fffffff;
struct station {
	double p; //每单位汽油价格
	double d; //离起始地点距离
	station() {
		p=0;
		d=0;
	}
} st[maxn];
bool cmp(station s1,station s2) {
	return s1.d<s2.d;
}
int main(int argc,char * argv[]) {
	// 1 接收数据

	// Cmax油箱容量;
	// D起点到终点距离;
	// Davg每单位汽油行驶距离
	int n; //n 加油站数量
	double Cmax,D,Davg;
	scanf("%lf%lf%lf%d",&Cmax,&D,&Davg,&n);
	for(int i=0; i<n; i++) {
		scanf("%lf%lf",&st[i].p,&st[i].d);
	}
	// 设置终点为哨兵 
	st[n].p=0;
	st[n].d=D;
	
	// 2 按照与起始点距离排序,从小到大
	sort(st,st+n,cmp);

	// 3 贪心寻找最优解

	// 题目已知起始油箱为0,所以起点一定要有一个油站
	if(st[0].d!=0) {
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	int now = 0; //当前站编号 
	double ans = 0;// 总花费
	double nowTank = 0;//当前剩余油量
	double MAX=Cmax*Davg; //满油最大行驶距离 
	while(now<n) {
		// 1 求当前站到达范围内(满油行驶距离),第一个油价低于当前站油价的站
		// 若找不到,就求出可达范围内最低油价的站
		int k=-1;
		double priceMin = INF;
		for(int i=now+1; i<=n&&st[i].d-st[now].d<=MAX; i++) {
			if(st[i].p<priceMin) {
				priceMin=st[i].p;
				k=i;
				if(priceMin<st[now].p) {
					break; //已找到比可达范围内,比当前站油价更低的站
				}
			}
		}

		if(k==-1)break; //可达范围内没有加油站,旅程失败
		double need = (st[k].d-st[now].d)/Davg; //从当前站到k站需要的油量
		if(priceMin<st[now].p) {
			// 如果可达范围内,有比当前油价更低的油站,只需要添加到达该站的油量
			if(nowTank<need) {
				ans+=(need-nowTank)*st[now].p;
				nowTank=0; //到达k站,汽油余量为0;
			} else {
				nowTank-=need; //到达k站,减掉消耗的汽油量
			}
		} else {
			ans+=(Cmax-nowTank)*st[now].p;
			nowTank=Cmax-need; //到达k站剩余汽油量
		}
		now = k;
	}
	if(now==n) {
		//能到达终点
		printf("%.2f\n",ans); 
	} else {
		printf("The maximum travel distance = %.2f\n",st[now].d+MAX);
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值