PatA1033 To Fill or Not to Fill 加油站 2020/8/11

问题描述

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.

解决方法

#include 
#include 
using namespace std;
const int maxn = 501;
//定义能够到达的最大距离
double enableDistance;
//定义加油站的基本信息
struct gasStation
{
    double distance;
    double price;
} station[maxn];
//按加油站的距离排序
bool cmp(gasStation a, gasStation b)
{
    return a.distance < b.distance;
}
/*
    根据策略选择下一个要到达的加油站
    如果可到达的范围内没有加油站就返回-1,
    如果范围内有比当前加油站便宜的最近的加油站就选择那个加油站(便宜的油越早用越好)
    如果范围内没有比当前加油站便宜的就选择范围内最便宜的加油站,并在当前加油站加满油再出发(便宜占尽了)
    返回的值+n可以标识出这种情况。
*/
int selectNext(int pos, int n)
{
    int res = pos + 1;
    if (station[res].distance > station[pos].distance + enableDistance)
        return -1;
    for (int j = res; j <= n; j++)
    {
        if ((station[j].price < station[pos].price) && (station[j].distance - station[pos].distance <= enableDistance))
        {
            return j;
        }
    }
    for (int j = pos + 2; j <= n; j++)
    {
        if ((station[j].distance - station[pos].distance <= enableDistance) && (station[j].price <= station[res].price))
        {
            res = j;
        }
    }
    return res + n;
}
int main(void)
{
    //获取基本信息
    double dAvg, cMax, d;
    int n;
    scanf("%lf %lf %lf %d", &cMax, &d, &dAvg, &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%lf %lf", &station[i].price, &station[i].distance);
    }
    //设置终点
    station[n].distance = d;
    station[n].price = 0.0;
    //排序
    sort(station, station + n + 1, cmp);
    //计算
    enableDistance = dAvg * cMax;
    //初始化当前位置以及支付的总价格
    int current = 0;
    double sumPrice = 0.0;
    //如果起点没有加油站就无法出发
    if (station[0].distance != 0)
    {
        printf("The maximum travel distance = 0.00");
        return 0;
    }
    else
    {
        //初始化剩余的油量
        double remainGas = 0.0;
        /*
            如果没有到终点,就选择下一个要到达的地点
            selectNext如果返回-1就以当前位置加上最大距离即为行驶的最远距离
            返回大于n表明是加满油的情况,小于则是找到了便宜的油的情况,分情况计算价格
            最后修改当前位置
        */
        while (current != n)
        {
            int res = selectNext(current, n);
            if (res == -1)
            {
                printf("The maximum travel distance = %.2f", (double)station[current].distance + enableDistance);
                return 0;
            }
            else
            {
                if (res > n)
                {
                    res = res - n;
                    sumPrice += station[current].price * (cMax - remainGas);
                    remainGas = cMax - (station[res].distance - station[current].distance) / dAvg;
                }
                else
                {
                    double useGas = (station[res].distance - station[current].distance) / dAvg;
                    /*
                        这里不会remainGas >= useGas,如果真的是这样就上一次就会直接越过此处加油站
                    */
                    sumPrice += ((useGas - remainGas) * station[current].price);
                    remainGas = 0.0;
                }
                current = res;
            }
        }
        printf("%.2f", sumPrice);
    }
    return 0;
}

基本策略

  • 在可到达的范围内寻找加油站
    • 如果有比当前更便宜的加油站在其中选择最近的加油站,只在当前加油站加入刚好能到达的油量(尽量早的使用到便宜的油)
    • 如果没有就对范围内的加油站进行筛选选择较便宜的加油站作为下一站并在当前加油站将油箱加满(没有就占满当前的便宜)

结果展示

pat1033.png

你可能感兴趣的:(PatA1033 To Fill or Not to Fill 加油站 2020/8/11)