A1033 To Fill or Not to Fill (25 分)

1033 To Fill or Not to Fill (25 分)

题目分析

       我跟这道题交手已经不下4次了,终于把它给AC了。这是一道贪心的问题,贪心的策略也比较好想,那就是保证油的单价一定是最便宜的。但是这其中有一些细节,如果不仔细很容易出错。

解题思路

       我们在每个站点考虑要加的油量,参照的标准是当前站点的油价和后续站点的油价。可能面临的情况有如下几种:

下一个站点能够到达

       这时有两种情况:

  1. 下一个站点的油价小于或等于当前站点
           此时的策略很简单,即保证油恰好够跑到下一个站点,如果此时油箱中的油量大于所需值,就不加。
  2. 下一个站点的油价大于当前站点
           如果在我们能够到达的最大距离内有油价小于我们的站点,那么就让油量保持到恰好够跑到这个站点;如果在我们能够到达的最大距离内没有油价小于我们的站点,那么就在当前站点把油箱加满。
           根据上述的分析我们需要一个参数c来记录当前油箱中的油量,在每次加油之后都要更新他的值。上述的策略能够保证是最优的策略,具体的证明略。

下一个站点不能到达

       这就是说两个站点之间的距离超过了满油能够跑的最大距离,那么显然我们无法到达目的地,此时输出能够到达的最大距离,也就是当前站点距离起点的距离加上满油能够跑的最大距离。
       最后还要注意的是可能第一个站点距离出发地的距离大于0,那么这个时候能够行驶的最大距离就是0.

AC代码


#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node {
	double p;
	double dis; // 从当前站点到下一个站点的距离
};
bool cmp(node a, node b) {
	return a.dis < b.dis;
}
vector<node> v;
double c_max, D, D_avg, d_max;
int n;
int main() {
	scanf("%lf %lf %lf %d", &c_max, &D, &D_avg, &n);
	d_max = c_max * D_avg;
	v.resize(n + 1);
	for (int i = 0; i < n; ++i) {
		double a, b;
		scanf("%lf %lf", &a, &b);
		v[i].p = a;
		v[i].dis = b;
	}
    sort(v.begin(), v.end() - 1, cmp);
    if (v[0].dis != 0) {
        printf("The maximum travel distance = 0.00\n");
        return 0;
    }
    for (int i = 0; i < n - 1; ++i) {
    	v[i].dis = v[i + 1].dis - v[i].dis;
    }
    v[n - 1].dis = D - v[n - 1].dis;
    v[n].dis = 0, v[n].p = 0;
    int i = 0;
    double cost = 0, c = 0;
    while(i <= n) {
        if (v[i].dis <= d_max) {  // 下一个站点能够到达
        	if (v[i].p >= v[i + 1].p) { // 下一个站点的油价小于或等于当前站点
        		if (v[i].dis / D_avg - c < 0) {
        			c -= v[i].dis / D_avg;
        		} else {
        			cost += (v[i].dis / D_avg - c) * v[i].p;
        			c = 0;
        		}
                i++;
        	} else {
        		int temp = i;
        		double sumd = v[i].dis;
        		i++;
        		while(sumd <= d_max && v[temp].p < v[i].p) {
        			sumd += v[i].dis;
        			i++;
        		}
        		if (sumd > d_max) { // 如果在能够到达的最大距离内没有油价更小的站点
        		    i--; // 这一句很容易漏掉,如果不仔细考虑的话
                    sumd -= v[i].dis;
        			cost += (c_max - c) * v[temp].p;
                    c = c_max - sumd / D_avg;
        		} else {
        			if (sumd / D_avg - c < 0) {
        				c -= sumd / D_avg;
        			} else {
        				cost += (sumd / D_avg - c) * v[temp].p;
        				c = 0;
        			}
        		}
        	}
        }
        else {
        	double d1 = 0;
        	for (int j = 0; j < i; ++j) {
        		d1 += v[j].dis;
        	}
        	printf("The maximum travel distance = %.2f\n", d1 + d_max);
        	return 0;
        }
    }
    printf("%.2f\n", cost);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值