洛谷P1016 旅行家的預算 [單調隊列]

傳送門
題意:給出n個加油站的位置posi和重點t以及每個加油站油的價格vi以及油箱的體積L,求最小花費

題解:如果油箱容量是無限大的那麼顯然可以直接使用優先隊列每經過一個加油站就直接丟進去價格然後每次需要加油就彈出即可,而這裏限制了油箱體積爲L,就不能無腦無限量地使用最小值,此時維護一個價格單調遞增的隊列,每次選取隊列頭的油進行消耗,每次經過加油站,彈出尾部比當前油費貴的油,然後插入體積爲L-油箱內剩餘的油的體積的當前油站的油即可

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<<x<<endl;

struct nod{
    double pos;
    double val;
}no[8];

struct que{
    double val;
    double res;
}q[8];

bool cmp(struct nod a,struct nod b){
    return a.pos<b.pos;
}

int main(){
    double d1,c,d2,p;
    int n;
    scanf("%lf%lf%lf%lf%d",&d1,&c,&d2,&p,&n);
    for(int i=1;i<=n;i++)scanf("%lf%lf",&no[i].pos,&no[i].val);
    sort(no+1,no+1+n,cmp);
    int head=1;
    int tail=0;
    q[++tail].res=c;
    q[tail].val=p;
    double ans=p*c;
    double sum=c;
    int F=1;
    for(int i=1;i<=n;i++){
        if(d1<=no[i].pos){
            double x=(d1-no[i-1].pos)/d2;
            while(head<=tail&&x){
                if(x<q[head].res){
                    q[head].res-=x;
                    x=0;
                    break;
                }
                else{
                    x-=q[head].res;
                    head++;
                }
            }
            if(x)F=0;
            while(head<=tail){
                ans-=q[head].res*q[head].val;
                head++;
            }
        }
        else{
            double x=(no[i].pos-no[i-1].pos)/d2;
            sum-=x;
            while(head<=tail&&x){
                if(x<q[head].res){
                    q[head].res-=x;
                    x=0;
                    break;
                }
                else{
                    x-=q[head].res;
                    head++;
                }
            }
            if(x){F=0;break;}
            while(head<=tail&&q[tail].val>=no[i].val){
                sum-=q[tail].res;
                ans-=q[tail].res*q[tail].val;
                tail--;
            }
            q[++tail].res=c-sum;
            ans+=(c-sum)*no[i].val;
            q[tail].val=no[i].val;
            sum=c;
        }
    }
    if(F&&d1>no[n].pos){
            double x=(d1-no[n].pos)/d2;
            while(head<=tail&&x){
                if(x<q[head].res){
                    q[head].res-=x;
                    x=0;
                    break;
                }
                else{
                    x-=q[head].res;
                    head++;
                }
            }
            if(x)F=0;
            while(head<=tail){
                ans-=q[head].res*q[head].val;
                head++;
            }
    }
    if(F)printf("%.2f\n",ans);
    else printf("No Solution\n");
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章