贪心—To Fill or Not to fill

0x00 题目地址

To Fill or Not to Fill__牛客网 (nowcoder.com)

0x01 分析

符合最优子结构、无后效性、重复子问题三个条件,因此可以使用贪心求解。 

先按照距离排序,将加油站排成一条线。

算法每一步的思路:

        1.首先判断油箱加满时的最大里程能否支撑到下一个加油站。(只需判断相邻的油站距离是否大于加满油的最大里程即可,不满足的话就可以输出最大路程,然后return 0)

        2.其次,寻找(current_location,current_location+最大里程]内油价最便宜的加油站

        2.1 若这个最便宜的油价甚至比当前加油站的更便宜,则只需确保油箱的油足够到下一站即可。

                2.1.1 可能油箱本来油量就够,那就不需要加        

                2.1.2 若油箱的油量不够,那么就加到足够到该加油站的油量即可,不需要多加。

        2.2 若这个最便宜的油价比当前加油站的还要贵。那么就在当前的加油站加满油。

最终判断路程是否==距离。然后打印输出总花费即可。

0x02 完整代码

#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct station {
	double price;
	double dis;
};

bool compare(station A, station B) {
	if (A.dis == B.dis) {
		return A.price < B.price;
	}
	return A.dis < B.dis;
}


int main() {
	double cmax, d, davg, n;
	while (cin >> cmax >> d >> davg >> n) {
		vector<station> station(n + 1);
		for (int i = 0; i < n; ++i)
		{
			cin >> station[i].price >> station[i].dis;
		}
		//将终点也作为加油站
		station[n].price = 0;			//将终点站也看成加油站
		station[n].dis = d;
		sort(station.begin(), station.end(), compare);

		double maxrun = cmax * davg;  //最大里程
		double run = 0;       //路程
		double cost = 0;		//总花费
		double fuel = 0;      //当前油箱的油量

		for (int i = 0; i < n; i++) {
			if ((station[i + 1].dis - station[i].dis )> maxrun) {
				printf("The maximum travel distance = %.2f\n", run + maxrun);
				return 0;
			}

			//寻找可行使区间内最便宜的加油站
			double cheapest = i+1;
			//寻找比当前的加油站油价还便宜的加油站
			double nearest = i+1;
			for (int j = i + 1; j < n + 1 && station[i].dis + maxrun >= station[j].dis; j++) {
				if (station[cheapest].price >= station[j].price) {
					cheapest = j;
				}

				if (station[j].price <= station[i].price) {
					nearest = j;
					break;
				}
			}

			if (station[cheapest].price > station[i].price) { //当前的油价比后面区间内的油价都便宜,则直接加满
				cost += station[i].price * (cmax- fuel);
				fuel = cmax;
				run += station[cheapest].dis - station[i].dis;
				fuel -= (station[cheapest].dis - station[i].dis) / davg; //减去到下一个加油站的油耗
				i = cheapest - 1; //要-1,因为for循环还有个i++
			}
			else { //油价比当前的站还便宜,只需加够足够支撑到下一加油站的油量即可
				//看看剩余的油箱是否能跑到那个站
				if (fuel < (station[nearest].dis - station[i].dis) / davg) { //如果跑不到下一个站,那就加适量的油
					cost += station[i].price * ((station[nearest].dis - station[i].dis) / davg - fuel);

					fuel = (station[nearest].dis - station[i].dis) / davg;
				}
				
				fuel -= (station[nearest].dis - station[i].dis) / davg; //减去到下一个加油站的油耗
				run += station[nearest].dis - station[i].dis;
				i = nearest - 1;
			}

		}

		if (run == d) {
			printf("%.2f\n", cost);
		}

	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ad_m1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值