牛客网 To Fill or Not to Fill(贪心)

题目传送门

To Fill or Not to Fill

题目描述

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.

输入描述:

For each case, the first line contains 4 positive numbers: Cmax (<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg (<=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: Pi, the unit gas price, and Di (<=D), the distance between this station and Hangzhou, for i=1,…N. All the numbers in a line are separated by a space.

输出描述:

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
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
50 1300 12 2
7.10 0
7.00 600
Sample Output
749.17
The maximum travel distance = 1200.00
题意

要从杭州出发去往另一个城市,告诉汽车的油桶大小,目的地距离,每单位燃料可以走的距离,中间的加油站个数,每个加油站数据由油价和位置坐标构成,问能否到达终点,可以输出最小花费,不可以则输出最远距离。

思路

贪心算法,如果起点没有加油站,则不可到达,加油站按照位置坐标,由远到近排序,位置相同则按照油价升序排列,具体策略为从起点开始不断寻找可达并且油价低于目前油价的加油站:

设油桶大小为Cmax ,终点坐标为ends,单位燃料可走距离为Davg ,汽车当前所在位置为car.pos,那么车在可到达的范围是 [ c a r . p o s    ,    c a r . p o s + C m a x ∗ D a v g ] [car.pos\space\space ,\space\space car.pos+Cmax*Davg] [car.pos  ,  car.pos+CmaxDavg],在这个范围寻找(终点不在范围之内时):

  • 如果存在加油站 g a s [ i ] gas[i] gas[i] 的油价比当前所在加油站 temp 油价更低:

    那么只需要车刚好到达 g a s [ i ] gas[i] gas[i] 即可(到达 g a s [ i ] gas[i] gas[i] 时车中油桶清空),对应的花销就只需要保证车辆刚好到达 g a s [ i ] gas[i] gas[i]

    ( ( t . p o s − t e m p . p o s ) / D a v g − c a r . t e m p g a s ) ∗ t e m p . p r i c e ((t.pos-temp.pos)/Davg-car.tempgas)*temp.price ((t.postemp.pos)/Davgcar.tempgas)temp.price

    t 为在上述范围中寻找到的加油站

  • 如果范围内的所有加油站都大于等于当前的加油站的油价:

    那么就把当前的油箱加满,并走到油价最低的加油站

  • 如果范围内没有加油站,为了走的更远,则加满油桶

如果终点在范围中

  • 寻找到油价低的情况不变
  • 如果找到油价高的或者没有加油站,就不需要加满,而是直接加刚好到终点即可

第一道完全靠自己A的贪心题,还是蛮有纪念意义的,不明白的话可以参考代码注释理解一下~

代码
#include <bits/stdc++.h>
using namespace std;
#define MAXN 520
#define INF 0x3f3f3f3f
struct node{
    double price;
    double pos;
    int id;
}gas[MAXN];
struct CAR{
    double pos;
    double tempgas;
    double cost;
}car;
bool cmp(node a,node b){
    if (a.pos==b.pos)return a.price<b.price;
    return a.pos<b.pos;
}
int main (){
    double cmax,ends,avgd;
    int n;
    while (scanf("%lf%lf%lf%d",&cmax,&ends,&avgd,&n)!=EOF){
        int flag=0;
        for (int i=0;i<n;i++){
            scanf("%lf%lf",&gas[i].price,&gas[i].pos);
            if (gas[i].pos==0)flag=1;
        }
        //起点没有加油站
        if (!flag){
            printf("The maximum travel distance = 0.00\n");
            continue;
        }
        //加油站按照坐标升序排序,坐标相同则按照油价升序排序
        sort(gas,gas+n,cmp);
        
        
        //给有序的加油站标号方便遍历
        for(int i=0;i<n;i++){
            gas[i].id=i;
        }
        
        //初始化汽车的油桶、花销、位置都为0
        car = CAR{0,0,0};
        
        //汽车加满油能走的最远距离
        double dmax = cmax*avgd;
        
        //当前所在的加油站,因为已经按照油价升序排序,所以第0个一定是最低的
        node temp=gas[0];
        
        while (car.pos<ends){
            node t=node{INF,INF,INF};
            //开始寻找当前加油站之后的加油站
            //满足距离需求
            //gas[i].pos<=car.pos+dmax && gas[i].pos>=car.pos
            for (int i=temp.id+1;gas[i].pos<=car.pos+dmax && gas[i].pos>=car.pos && i<n;i++){
                //找到加油站
                if (gas[i].price<t.price){
                    t=gas[i];
                    //如果比目前的加油站油价更低,则可以先到达这个加油站
                    if (t.price<temp.price)break;
                }
            }

            if (t.price<=temp.price){
                //找到的价格更低的加油站
                car.pos=t.pos;
                //如果油箱还有,则加到刚好到t即可
                car.cost+=((t.pos-temp.pos)/avgd-car.tempgas)*temp.price;
                //清空油箱
                car.tempgas=0;
                temp=t;
            }else {//没找到价格更低的加油站
                //如果终点可达,需要加 刚好到达终点的 油
                if (car.pos+dmax>=ends){
                    car.pos=ends;
                    car.cost+=((ends-temp.pos)/avgd-car.tempgas)*temp.price;
                }else if (t.price==INF){
                    //如果没有加油站,则说明无法到达终点,直接加满
                    car.pos+=dmax;
                    car.cost+=(cmax-car.tempgas)*temp.price;
                    break;
                }else if (t.price>temp.price){
                    //如果油价贵了,则在当前加油站加满,计算除剩余量以及花销
                    car.pos=t.pos;
                    car.cost+=(cmax-car.tempgas)*temp.price;
                    car.tempgas=cmax-(t.pos-temp.pos)/avgd;
                    temp=t;
                }
            }
        }
        if (car.pos>=ends){
            printf("%.2f\n",car.cost);
        }else {
            printf("The maximum travel distance = %.2f\n",car.pos);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值