TOPS [NOIP1999 提高组] 旅行家的预算

#include <bits/stdc++.h>
using namespace std;

double di[101], pi[101], d, c, d0;
int n;

// 寻找下一个加油站 
int find_min(int start)
{
    if(start == n) return n+1;
    double dend = di[start] + c*d0;
    int k = n;
    while(di[k]-di[start] > dend) k--;
    if(k == start)       // 开不到下一个加油站 
        return -2; 
    for(int i = k-1; i >= start+1; i--)
    {
        if(pi[i] < pi[k])
            k = i;
    }
    if(pi[k] > pi[start])    // 后面没有更便宜的加油站 
    {
        if(dend >= di[n+1])  // 能开到终点 
            return n+1;     
        return -1;       // 开不到终点 
    } 
    return k;
}

int main()
{
    cin >> d >> c >> d0 >> pi[0] >> n;  
    if(n == 0)   // 中间没有加油站 
    {
        if(c*d0 >= d)
            printf("%.2lf", d/d0*pi[0]);
        else
            printf("No Solution");
        return 0;
    }
    for(int i = 1; i<= n; i++)
    {
        cin >> di[i] >> pi[i];
    }
    di[n+1] = d; 
    int cur = 0, next;
    double rest = 0, cost = 0;
    while(1)
    {
        next = find_min(cur);   // 找到从当前加油站能开到的最远的加油站 
        //printf("now:%d, next:%d, rest:%.2lf, dist:%.2lf\n", cur, next,rest,rest*d0);
        if(next == n+1)   // 如果能开到终点 
        {
            if(rest*d0 < di[n+1]-di[cur])
            {
                //printf("加%.2lf钱\n",(di[n+1]-di[cur]-rest*d0)/d0*pi[cur]);
                cost += (di[n+1]-di[cur]-rest*d0)/d0*pi[cur];
            }
//          else
//              printf("不用加油\n");
            // 加能开到终点的油 
            printf("%.2lf", cost);
            return 0;
        }
        else if(next == -1)   // 开不到终点,且没比当前更便宜的加油站
        {
            // 加满油,开到下一个加油站 
            //printf("加满, 加%.2lf钱\n", (c-rest)*pi[cur]);
            cost += (c-rest)*pi[cur];
            rest = c - (di[cur+1]-di[cur])/d0; 
            cur++;
        }
        else if(next == -2)
        {
            printf("No Solution");
            return 0;
        } 
        else                 // 有更便宜的加油站,开到该加油站 
        {
            if(rest*d0 < di[next]-di[cur])
            {
                //printf("该加油站便宜,加%.2lf钱\n", (di[next]-di[cur]-rest*d0)/d0*pi[cur]);
                // 只加刚好够行使到该加油站的油量 
                cost += (di[next]-di[cur]-rest*d0)/d0*pi[cur];
                rest = 0;
            }
            else
            {
                //printf("不加油,够用\n");
                rest -= (di[next]-di[cur])/d0; 
            }
            cur = next;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值