1033 To Fill or Not to Fill (25 分)

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive numbers: C
​max
​​ (≤ 100), the maximum capacity of the tank; D (≤30000), the distance between Hangzhou and the destination city; D
​avg
​​ (≤20), the average distance per unit gas that the car can run; and N (≤ 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: P
​i
​​ , the unit gas price, and D
​i
​​ (≤D), the distance between this station and Hangzhou, for i=1,⋯,N. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print The maximum travel distance = X where X is the maximum possible distance the car can run, accurate up to 2 decimal places.

Sample Input 1:

50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300

Sample Output 1:

749.17

Sample Input 2:

50 1300 12 2
7.10 0
7.00 600

Sample Output 2:

The maximum travel distance = 1200.00

解决方案

解决这道题目需要利用贪心算法,怎么贪心呢?,规则是这样的:
为每个加油的站点设置一个结构体Node,存放这个站点距离起点的距离dis,和这个站点的油价price

  • 在当前站点加满油后能到达的范围内,若不存在加油站则计算出加满油后能到达的最大距离,输出结果,程序结束。
  • 若存在有比当前站点价格更便宜的站点,就在当前站点加能开到那个距离当前站点最近且价格更便宜的站点的油量即可。
  • 若在这个范围内找不到价格比当前站点更便宜的站点,则在当前站点加满油,并开到范围内价格最便宜的站点,然后重复上面的步骤,直到到达终点。

ps:在进行上面的步骤之前需要对站点按距离排序,若不存距离为0的加油站则直接输出最大距离为0,程序结束
如何知道要到达终点了?

  • 在第二种情况下判断下个相邻的站点的dis值是否大于终点距离,是则在当前站点只加到达终点的油
  • 若是第三种情况则直接判断当前站点能到达的最大距离是否大于终点的距离即可,是则在当前站点只加到达终点的油
  • 若当前节点是最后一个站点,则判断加满油到达的最大距离是否大于终点的距离,是则在当前站点只加到达终点的油
    AC代码
#include<iostream>
#include<algorithm>
#include<vector>
#define INF 0x7fffffff
using namespace std;
struct Node {
	double price;
	double dis;
	Node(double _price, double _dis) {
		price = _price;
		dis = _dis;
	}
};
vector<Node> v;
bool cmp(Node n1, Node n2) {
	return n1.dis < n2.dis;
}
int main() {
	//freopen("C:\\Users\\maoalong\\Desktop\\test.txt","r",stdin);
	int Cmax, Davg, n,flag=0;
	double D;
	scanf("%d%lf%d%d", &Cmax, &D, &Davg, &n);
	for (int i = 0; i < n; i++) {
		double dis;
		double price;
		scanf("%lf %lf", &price, &dis);
		v.push_back(Node(price, dis));
		
	}
	sort(v.begin(), v.end(), cmp);
	if(v[0].dis>0){
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	double sum = 0;
	double tank = 0;
	for (int i = 0; i < n; ) {
		double maxDis = v[i].dis + Davg * Cmax;
		int j = i+1;
		double min = j;
		//maxDis范围内没有站点可以加油 
		if((i==n-1&&maxDis<D)||(j<n&&v[j].dis>maxDis)){
			printf("The maximum travel distance = %.2f",maxDis);
			return 0;
		}
		//最后一个加油站加满油是否能到 
		if(i==n-1&&maxDis>=D){
			sum+=((D-v[i].dis)/Davg-tank)*v[i].price;
			printf("%.2f",sum);
			return 0;
		} 
		
		int flag = 0;//判断是否存在价格比当前站点更便宜的站点
		for ( ; v[j].dis <=maxDis&&j<n; j++) {
			//发现了比当前站点更便宜的站点,就只加能开到那个站点的油 
			if (v[j].price < v[i].price) {
				
				if(v[j].dis>=D){
					sum+=((D-v[i].dis)/Davg-tank)*v[i].price;
					printf("%.2f",sum);
					return 0;
				} 
				double tmp = (v[j].dis - v[i].dis) / Davg;
				tmp-=tank;
				tank = 0;
				sum +=tmp*v[i].price;
				flag = 1;
				break;
			}
			//寻找在maxDis范围内最便宜的站点 
			if (v[j].price <v[min].price) {
				min = j;
			}
		}
		//如果没有找比当前站点更便宜的站点,那么就去这个范围内最便宜的站点 
		if (!flag) {
			if(D<=maxDis){
				sum += ((D-v[i].dis)/Davg - tank)*v[i].price;//在当前站点需要加满到达终点的油 
				printf("%0.2f",sum);
				return 0;
			}
			sum+=(Cmax-tank)*v[i].price;
			tank = Cmax - (v[min].dis - v[i].dis) / Davg;//计算出行驶到相对最便宜的站点后剩余的流量 
			j = min;
		}
		i = j; 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值