题解 P1016 【旅行家的预算】

· · 题解

贪心 AC

------------(利用了简单的队列存要走的油站)

好不容易AC了翻翻评论区,决心认认真真哒写个题解造福和自己一样的小可爱们

注释写的炒鸡清楚啦QAQ!蒟蒻在第四个点上卡了1hour
#include<iostream>
#include<cstdio>
#include<queue> 
using namespace std;
double all,each,c,full;
double dis[10],price[10],cost,oil,add,need;
int n,tmp,now;
queue<int>q;                //用队列表示走过的油站 
int main(){
    scanf("%lf%lf%lf%lf%d",&all,&c,&each,&price[0],&n);         //读入 
    tmp=0,full=each*c;          //full表示单次最大行驶距离 
    dis[n+1]=all;               //存入到达终点用的距离 
    price[n+1]=99999999;        //将到达终点的价格初始化为最大值(用于之后进行比较) 
    for(int i=1;i<=n;i++) scanf("%lf%lf",&dis[i],&price[i]);    //读入 
    for(int i=1;i<=n+1;i++){
        if(dis[i]-dis[i-1]>full){               //如果两油站间距离超过最大到达距离,结束程序 
            printf("No Solution");
            return 0;
        }
        if(price[i]<price[tmp]&&dis[i]-dis[tmp]<=full){     //如果该油站油费<当前位置油站的油费,且能够抵达,加入队列 
            q.push(i);
            tmp=i;                  //更新当前油站的位置 
        }
        else if(dis[i]-dis[tmp]>full){      //如果该油站距离>最大行驶距离 
            q.push(i-1);        //将前一个油站加入队列 
            tmp=i-1;            // 将当前油站的位置更新为前一个油站 
            i--;                //重新比较当前油站 
        }
    }
    q.push(n+1);            //将终点加入队列 
    price[n+1]=0;           //因为比较结束,将终点油费更改为0 
    while(q.size()){
        int x=q.front();        //x表示要到达的油站 
        q.pop();
        if(price[x]>price[now]){        //如果要到达的油站油费>当前油站油费 
            add=c-oil;  //加满油 
            oil=c-(dis[x]-dis[now])/each;   //更改油量 
            cost+=add*price[now];   //记录费用 
        }
        else{   // 如果要到达的油站油费<=当前油站油费 
            need=(dis[x]-dis[now])/each;    // need表示需要的油量 
            if(oil>=need) oil-=need;    //如果当前油量大于需要的,不加油
            else{       // 如果当前油量不够,加刚好到达下一站的油 
                add=need-oil;
                oil+=add-need;  //更改油量 
                cost+=add*price[now];   //记录费用 
            }
        }
        now=x;  //更改当前油站位置 
    }
    printf("%.2lf",cost);   //输出 
}