旅行家的预算(洛谷)

27 篇文章 1 订阅

题目链接:旅行家的预算

解题思路:题目的目标是求出最小的油费,如果我们知道在每个加油站都加了多少升油,那就可以求出油费了,最小也就意味着在每个加油站加的油最合适。思考什么叫做合适,假设我当前处在第index个加油站(起始在第0个),如果我把油加满了,最远能走到的距离假设为maxdist,如果从当前加油站到maxdist中还有其他加油站的邮费比当前加油站油费低,那我就可以走到那个加油站(next)进行加油,我在index加的油刚好走到next就行。

解题过程:上面是本题的关键思路,在解题过程中需要考虑多中情况。看代码注释

#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double> PDD;
const int N = 510;
double d1,c,d2,p;
int n;
PDD d[N];
bool cmp(PDD &p1,PDD &p2)
{
    return p1.first < p2.first;
}
int main()
{
    cin>>d1>>c>>d2>>p>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>d[i].first>>d[i].second;
    }
    d[0].first = 0;
    d[0].second = p;
    sort(d,d+n,cmp);
    double cost = 0; //油费
    int index = 0;//当前所在的加油站位置
    int flag = 1;//标记是否可以到达目的地
    double mg = 0;//邮箱里剩余的油
    while(index <= n)
    {
        double dist = c*d2;//从这个加油站加满油开始,我可以走多远
        int next = -1;
        double rest;
        double need;
        for(int i=index+1;i<=n;i++)
        {
            double temp = d[i].first - d[index].first;
            //cout<<temp<<" "<<dist<<" "<<d[i].second<<" "<<d[index].second<<endl;
            if(temp <= dist&&d[i].second<=d[index].second)
            {
                next = i;
                break;
            }
        }
        //cout<<next<<endl;
        if(index == n)
        {
            //如果这已经是最后一个加油站了
            double rest = d1-d[index].first;
            if(dist < rest)
            {
                //最后一个加油站加满油都到不了
                flag = 0;
            }
            else
            {
                //最后一个加油站加满可以到达
                need = (rest - mg*d2)/d2;//这一段路要加的油
                cost+=need*d[index].second;
            }
            break;
        }
        if(next!=-1)
        {
            //如果我剩余的油量可以到达next位置,那我就不需要在index位置进行加油
            
            double temp = d[next].first-d[index].first;
            if(mg*d2 >= temp)
            {
                mg-=(temp/d2);
                index = next;
            }
            else
            {
                //从index走到next更新距离,我在当前位置只需加到刚好可以走到next位置的油
                need = (temp-mg*d2)/d2;
                cost+=need*d[index].second;
                index = next;
            }

        }
        else
        {
            //后面有油站但是都比我贵,那我就在这个油站加满,看看能不能到达终点,能到就直接到,否则到下一个油站再说
            double rest = d1-d[index].first;
            if(rest < c*d2)
            {
                need = rest/d2;
                cost+=(need*d[index].second);
                break;
            }

            next = index+1;
            double temp = d[next].first-d[index].first;
            if(temp > c*d2)
            {
                //我在这个油站加满了油都走不到下一个油站
                flag = 0;
                break;
            }
            else
            {
                //可以走到下一个油站,计算剩余的油量以及油费
                need = c-mg;
                cost+=need*d[index].second;
                mg = c-(temp/d2);
                index = next;
            }

        }
        //cout<<"seclect: "<<index<<" "<<"rest oil: "<<mg<<" "<<"need: "<<need<<" "<<cost<<endl;
    }
    if(flag == 0)
    {
        cout<<"No Solution"<<endl;
    }
    else printf("%.2f",cost);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值