PAT 1033 To fill or not to fill

这是一道比较经典的贪心+模拟。
首先说一下大致思路吧:
贪心的关键是要考虑到两种情况:
遍历从当前油站的下一个油站 到 可以到达的最后一个油站:
1、如果碰到油站价格比当前油站价格低,那么就直接退出循环(我们记这个油站为下一个油站),此时在当前油站加的油量应该为(当前油站到下一个油站的距离 - remaining)所需要的油量。(remaining下面一种情况会解释它是什么意思)
2、如果没有比当前油站价格更低的,那么就选择一个相对较低的(下面还是一样称呼它为下一个油站),此时应该加的油量计算方式就大不相同了,这时候应该加满,具体也就是(Cmax*Davg - remaing)这么长的路程所需要的油量。然后更新remaining,remaing的意思就是从当前油站走到下一个油站之后还可以走多远。
Note:remaining只在一种情况下会产生,就是从当前油站可达的其他油站价格中没有比当前的价格更小的,按照贪心的想法,我肯定要在便宜的地方多拿一点。!!!remaining仅仅会影响下一个要去的油站所要加的油量,考虑到这样一个事实,下下一个油站是不可达的,到了下一个油站之后,我们便会将remaining清零(无论是第一种情况还是第二种情况),第二种会先清零再更新。
坑点:1、有一种情况是起点没有油站,所以最大可达就是0。
2、要考虑可能有很多油站在某一个相同的距离处。
3、边界的处理,如果从当前油站可以直接到终点,且中途没有比它价格更低的,那么就直接退出循环,具体可见代码。

#include<bits/stdc++.h>
using namespace std;

bool compare(pair<double, double>& a, pair<double, double>& b) {
	if (a.second == b.second) {
		return a.first < b.first;
	}
	return a.second < b.second;
}

int main() {
	double Cmax, D, Davg;
	int N;
	cin >> Cmax >> D >> Davg >> N;
	vector<pair<double, double>> stationInfo(N); // first is price, second is distance
	for (int i = 0; i<N; ++i) {
		cin >> stationInfo[i].first >> stationInfo[i].second;
	}
	sort(stationInfo.begin(), stationInfo.end(), compare);

    if(stationInfo[0].second != 0) {//坑点:有可能第一个油站不在起点
        printf("The maximum travel distance = 0.00");
        return 0;
    } 

	int curPos = 0;
	double ans = 0;

	int maxReach = Cmax * Davg;
	int reachable = 0;
	int remaining = 0;
	while (curPos < N) {
		double minP = 2 << 20;
		int index;
		int nextPos = 0;
		int flag = 0;
		int i;
		for (i = curPos + 1; i < N && stationInfo[i].second <= stationInfo[curPos].second + maxReach; ++i) {
			flag = 1;
			if (stationInfo[i].second == stationInfo[curPos].second)
				continue;
			if (stationInfo[i].first < stationInfo[curPos].first) {
				nextPos = i;
				break;
			}
			if (stationInfo[i].first < minP) {
				minP = stationInfo[i].first;
				index = i;
			}
		}
		if (i == N) {
			if (stationInfo[curPos].second + maxReach >= D) {
				break;
			}
		}
		if (!flag)break;
		int f = 1;
		if (!nextPos) {
			f = 0;
			nextPos = index;
		}
		if (f) {
			ans += (stationInfo[nextPos].second - stationInfo[curPos].second - remaining) / Davg * stationInfo[curPos].first;
			remaining = 0;
		}
		else {
			ans += (maxReach - remaining) / Davg * stationInfo[curPos].first;
			remaining = 0;
			remaining += maxReach - (stationInfo[nextPos].second - stationInfo[curPos].second);
		}
		reachable = stationInfo[nextPos].second;
		curPos = nextPos;
	}

	if (reachable + maxReach < D) {
		printf("The maximum travel distance = %.2f\n", reachable + Cmax * Davg);
	}

	else {
		ans += (D - stationInfo[curPos].second ) / Davg * stationInfo[curPos].first;
		printf("%.2f\n", ans);
	}

	//system("pause");
    return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值