一个餐厅在
n
≤
2
e
3
n\leq2e3
n≤2e3的天内,每天都需要一些餐巾,第
i
i
i天需要
r
i
r_i
ri的餐巾的数量,每天餐厅都可以花
p
p
p买一个新的餐巾。另外每天都可以把若干个餐巾送到快洗店或者慢洗店,快洗店是需要花
f
f
f块,洗
m
m
m天。慢洗店需要花
s
s
s块,洗
n
n
n天,也可以把餐巾保留到下一天。
对建图能力要求比较高的费用流,好题。每一天都拆成两个点,分别代表白天和晚上,白天是处理干净的餐巾,而晚上是处理被用完的餐巾。
源点向每个白天连无限流量
f
f
f权值,代表我可以任意购买新的餐巾。
每个白天向汇点连
c
i
c_i
ci流量
0
0
0权值,表示我最终需要的是
c
i
c_i
ci条餐巾。
源点向每个晚上连
c
i
c_i
ci流量
0
0
0权值,表示我要分配的是
c
i
c_i
ci条餐巾。
每个晚上向下一个晚上连无限流量
0
0
0权值,表示我可以延期送洗。
每个晚上向下
m
m
m个白天连无限流量
f
f
f权值,表示快洗。
每个晚上向下
n
n
n个白天连无限流量
s
s
s权值,表示慢洗。
跑最小费用流为答案。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
namespace MCMF {
const int N=4e3+7,M=1e5+7;
int tot=-1,n,S,T;
int front[N],pre[N],lst[N];
ll flow[N],dis[N];
bool inq[N];
struct edge{ int v,nxt;ll c,w; }e[2*M];
void init() {
tot=-1;
for(int i=1;i<=n;i++) front[i]=-1;
}
void add(int u,int v,ll c,ll w) {
e[++tot].v=v,e[tot].w=w,e[tot].c=c,e[tot].nxt=front[u],front[u]=tot;
e[++tot].v=u,e[tot].w=-w,e[tot].c=0,e[tot].nxt=front[v],front[v]=tot;
}
void reset() {
pre[T]=-1;
for(int i=1;i<=n;i++) dis[i]=flow[i]=1e15;
for(int i=1;i<=n;i++) inq[i]=0;
}
bool spfa() {
reset();
queue<int> q;
q.push(S);
inq[S]=1;dis[S]=0;
while(!q.empty()) {
int u=q.front();
q.pop();
inq[u]=0;
for(int i=front[u];i!=-1;i=e[i].nxt) {
int v=e[i].v;
if(e[i].c>0) {
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
flow[v]=min(flow[u],e[i].c);
pre[v]=u,lst[v]=i;
if(!inq[v]) {
inq[v]=1;
q.push(v);
}
}
}
}
}
return pre[T]!=-1?1:0;
}
pair<ll,ll> solve() {
ll maxflow=0,mincost=0;
while(spfa()) {
int cur=T;
maxflow+=flow[T];
mincost+=flow[T]*dis[T];
while(cur!=S) {
e[lst[cur]].c-=flow[T];
e[lst[cur]^1].c+=flow[T];
cur=pre[cur];
}
}
return make_pair(maxflow,mincost);
}
}
const int N=2e3+7;
int c[N];
int main() {
int N,p,m,f,n,s;
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d",&c[i]);
scanf("%d%d%d%d%d",&p,&m,&f,&n,&s);
MCMF::n=2*N+2;
int S=2*N+1;
int T=2*N+2;
MCMF::S=S;
MCMF::T=T;
MCMF::init();
for(int i=N+1;i<=2*N;i++)
MCMF::add(S,i,1e15,p);
for(int i=N+1;i<=2*N;i++)
MCMF::add(i,T,c[i-N],0);
for(int i=1;i<=N;i++)
MCMF::add(S,i,c[i],0);
for(int i=1;i+1<=N;i++)
MCMF::add(i,i+1,1e15,0);
for(int i=1;i+m<=N;i++)
MCMF::add(i,i+N+m,1e15,f);
for(int i=1;i+n<=N;i++)
MCMF::add(i,i+N+n,1e15,s);
ll ans=MCMF::solve().second;
printf("%lld\n",ans);
return 0;
}