Vijos 1253 旅行家的预算

题目链接:https://vijos.org/problems/P1253

描述

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离d1、汽车油箱的容量c(以升为单位)、每升汽油能行驶的距离d2、出发点每升汽油价格p和沿途油站数n,油站i离出发点的距离d、每升汽油价格p。
计算结果四舍五入至小数点后两位。
如果无法到达目的地,则输出-1。

格式

输入格式

输入共n+1行,第一行为d1,c,d2,p,n,以下n行,每行两个数据,分别表示该油站距出发点的距离d和该油站每升汽油的价格p。两个数据之间用一个空格隔开。

输出格式

一行,输出最少费用。
计算结果四舍五入至小数点后两位。
如果无法到达目的地,则输出-1。


本题练习贪心算法。

分析:走到能走到之内的第一个价格比当前所在点便宜的加油站,如果之后能走到的所有站都比当前点贵 那么就加满油 走到能走到的最便宜的一个站。

 如果在这个范围内存在一个加油站j,它的价格pri[j]<pri[i],那么只要把油加到刚好能到达j就可以了;如果在这个范围内不存在这样的加油站,那么就在i加满油,然后走到最便宜的加油站j,如果无法走到j,即最近的加油站dis[j]>dis[i]+c*d2,此时无解。

代码:

#include <stdio.h>
#include <stdlib.h>

using namespace std;

#define maxn 102

double d[maxn];//距离
double c;//容量
double d2;//每升油能行驶的距离
double p[maxn];//汽油价格
int n;//加油站个数

double cost;//花费
double rest;//油箱油量剩余

int main()
{
    /*#ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif*/
    double d1;
    scanf("%lf %lf %lf %lf %d",&d1,&c,&d2,&p[0],&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf %lf",&d[i],&p[i]);
    }
    d[n+1] = d1;
    p[n+1] = 0;
    d[0] = 0;

    cost = 0;
    rest = 0;

    int k = 0;
    while(k<=n)
    {
        int j = k;
        int flag = 0;
        int min = 0;
        double need = 0;//在k处需要加多少油
        while(d[j+1] - d[k] <= c * d2 && j<=n)
        {
            j++;
            //最近的比当前加油站低的
            if(flag == 0 && p[j]<p[k])
            {
                flag = j;
            }
            //最便宜的站
            if(min == 0 || p[j]<p[min])
            {
                min = j;
            }
        }
        if(k == j)
        {
            printf("-1\n");
            return 0;
        }
        //没有比当前加油站价格低的,加满,走到最便宜的一个站
        if(flag == 0)
        {
            need = c - rest;
            cost += need * p[k];
            rest = c - (d[min] - d[k])/d2;
            k = min;
        }
        //最近的比当前加油站低的
        else
        {
            need = (d[flag] - d[k])/d2 - rest;
            if(need < 0)
            {
                need = 0;
            }
            cost += need * p[k];
            rest = 0;
            k = flag;
        }
    }
    printf("%0.2lf\n",cost);

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值