PAT(甲级)1033 To Fill or Not to Fill (25point(s))

题目

题目链接

思路

题目大意:给出一些加油站以及他们各自油的价格,问如何选择加油策略使得总花费最小;
第一步,我们肯定要将加油站的距离按从小到大的顺序排好;
排好后有一种特殊情况特判一下,如果第一个加油站不在起点,那么这个车就哪也去不了,当然应该直接返回;
接下来考虑策略的选择;对一个加油站i来说,我们肯定会去看在当前加油站i加满油的情况下最远到达的加油站内有没有比i更便宜的,这里分为三种情况:
1、如果有比i更便宜的加油站 j (注意,这里需要选第一个比i便宜的加油站),我们就要看此时油箱中的油能不能到达j,如果能继续走;如果不能需要在这个加油站加一点油,使其到达j时恰好消耗完油;
2、如果没有比i更便宜的加油站,就需要选择先到相对最便宜的那个j,此时,需要在当前加油站 i 加满油;这里为什么要加满呢,因为下一个比i便宜的加油站即使加满油了也不能到达,需要先到这个相对便宜点的加油站j补充点油,早晚都得加,况且在i加便宜;
3、如果不能到达任何加油站,直接退出;

代码
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 510;

double C, D, Davg;//油箱容量,总距离,每升油所走距离,加油站数量
int N;

struct node{
     double price, dis;
}gas[maxn];

bool cmp(node a, node b){
     return a.dis < b.dis;
}

int main()
{
     scanf("%lf%lf%lf%d", &C, &D, &Davg, &N);
     for(int i = 0; i < N; i ++){
          scanf("%lf%lf", &gas[i].price, &gas[i].dis);
     }
     //将终点输入
     gas[N].price = 0, gas[N].dis = D;
     sort(gas, gas + N + 1, cmp);//将加油站按距离从小到大排序
     //特判第一个加油站不在起点的情况
     if(gas[0].dis != 0){
          printf("The maximum travel distance = 0.00\n");
          return 0;
     }
     double curCost = 0, curTank = 0;//当前总花费,当前油量
     int curGas = 0;//当前所在加油站
     while(curGas != N){
          //计算从当前加油站加满油出发最远到达的距离
          double maxx = C * Davg + gas[curGas].dis;
          int nextGas = curGas + 1;//下一目标油站
          for(int j = nextGas; gas[j].dis <= maxx; j ++){
               //如果找到一个更便宜的加油站
               if(gas[j].price < gas[curGas].price){
                    nextGas = j;
                    break;
               }
               //随时更新能到达的最便宜的加油站,以防没有比当前加油站价格更低的
               if(gas[j].price < gas[nextGas].price) nextGas = j;
          }
          //如果即使加满油也没有找到加油站
          if(nextGas == curGas + 1 && gas[nextGas].dis > maxx) {
               printf("The maximum travel distance = %.2f\n", maxx);
               return 0;
          }
          double need = (gas[nextGas].dis - gas[curGas].dis) / Davg;//从当前到下一加油站所需油量
          //下一加油站的价格低于当前价格
          if(gas[nextGas].price < gas[curGas].price){
               //如果所剩的油不够到达下一加油站,加到够就行
               if(curTank < need){
                    curCost += (need - curTank) * gas[curGas].price;
                    curTank = need;//加到油够用就行
               }
          }
          else{
               curCost += (C - curTank) * gas[curGas].price;
               curTank = C;//把油箱加满
          }
          //未进入下一状态做准备,油箱减少
          curTank -= need;
          curGas = nextGas;
     }
     printf("%.2f\n", curCost);
     system("pause");
     return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值