bzoj 5164: 餐厅计划问题

5164: 餐厅计划问题

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 86  Solved: 23
[Submit][Status][Discuss]

Description

一个餐厅在相继的n天里,每天需用的餐巾数不尽相同。假设第i天(i=1,2,...,n)需要ri块餐巾。餐厅可以在任意
时刻购买新的餐巾,每块餐巾的费用为P。使用过的旧餐巾,则需要经过清洗才能重新使用。把一块旧餐巾送到清
洗店A,需要等待m1天后才能拿到新餐巾,其费用为c1;把一块旧餐巾送到清洗店B,需要等待m2天后才能拿到新餐
巾,其费用为c2。例如,将一块第k天使用过的餐巾送到清洗店A清洗,则可以在第k+m1天使用。请为餐厅合理地安
排好n天中餐巾使用计划,使总的花费最小。
 

 

Input

第一行,包含六个个正整数n,m1,m2,c1,c2,p
接下来输入n行,每行包含一个正整数ri。
1≤n≤200000,1≤m1,m2≤n,1≤c1,c2,p≤100,1≤ri≤100
 

 

Output

输出一行,包含一个正整数,表示最小的总花费
 

 

Sample Input

4 1 2 2 1 3
8
2
1
6

Sample Output

35
第1天:买8块餐巾,花费24。送2块餐巾去清洗店A,6块餐巾去清洗店B。
第2天:取回2块清洗店A的餐巾,花费4。送1块餐巾去清洗店B。
第3天:取回6块清洗店B的餐巾,花费6。
第4天:取回1块清洗店B的餐巾,花费1。这样就用了最少的钱。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 200010
#define INF 1000000000
using namespace std;
int d,n1,n2,c1,c2,tc,a[maxn],sum;
deque<pair<int,int> >q;
int check(int x){
    q.clear();
    int res=x*(tc-c2);
    q.push_back(make_pair(1-n2,x));
    for(int i=1;i<=d;i++){
        if(i>n1)q.push_back(make_pair(i-n1,a[i-n1]));
        int now=a[i];
        while(now){
            if(q.empty())return INF;
            if(q.front().first+n2<=i){
                pair<int,int>x=q.front();q.pop_front();
                int t=min(now,x.second);
                x.second-=t;now-=t;res+=t*c2;
                if(x.second)q.push_front(x);
            }
            else {
                pair<int,int>x=q.back();q.pop_back();
                int t=min(now,x.second);
                x.second-=t;now-=t;res+=t*c1;
                if(x.second)q.push_back(x);
            }
        }
    }
    return res;
}
int main(){
    scanf("%d%d%d%d%d%d",&d,&n1,&n2,&c1,&c2,&tc);
    for(int i=1;i<=d;i++)scanf("%d",&a[i]),sum+=a[i];
    c1=min(c1,tc);c2=min(c2,tc);
    if(n1>n2)swap(n1,n2),swap(c1,c2);
    c2=min(c1,c2);
    int ans=INF,l=1,r=sum;
    while(r-l>=5){
        int mid1=(2*l+r)/3,mid2=(l+2*r)/3;
        int lc=check(mid1),rc=check(mid2);
        if(lc<rc)r=mid2;
        else l=mid1;
    }
    for(int i=l;i<=r;i++)ans=min(ans,check(i));
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-04-13 15:22  Echo宝贝儿  阅读(553)  评论(0)    收藏  举报