bzoj 5164: 餐厅计划问题
5164: 餐厅计划问题
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 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
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。这样就用了最少的钱。
第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; }
浙公网安备 33010602011771号