​题目​

解析:

二分图。\(X\)集合中的\(x_i\)表示第\(i\)天用掉的餐巾数量,\(Y\)集合中的\(y_i\)表示第\(i\)天需要的餐巾。建图时,从源点\(s\)向集合\(X\)中的每一个点连一条容量为\(r_i\)的边,从集合\(Y\)中的每一个点向汇点\(t\)连一条容量\(r_i\)的边来限制第\(i\)天用的餐巾。每天用完的餐巾有以下四个去向:

  1. 选择留到下一天\(x_i->x_{i+1}\),花费为\(0\)。
  2. 送到快洗部\(x_i->y_{i+d1}\),费用为\(c1\)。
  3. 送到慢洗部\(x_i->y_{i+d2}\),费用为\(c2\)。
  4. 每天需要的餐巾除了刚刚洗好的餐巾,还可能是新购买的\(s->y_i\),费用为\(c\)。
    建完图后跑一边费用流即可。

code:

#include <bits/stdc++.h>
using namespace std;

const int Maxn=2005;
const int Maxm=6000;
const int inf=0x3f3f3f;
int n,m,s,t,c,d1,c1,d2,c2,size=-1,x,sum;
int first[Maxn],tmp[Maxn],dis[Maxn],vis[Maxn];
struct shu{int to,next,l,c;}e[Maxm<<1];

inline int get_int()
{
int x=0,f=1;char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}

inline int min(int x,int y){return x>y ? y : x;}

inline void add(int x,int y,int l,int c)
{
e[++size].next=first[x],first[x]=size,e[size].to=y,e[size].l=l,e[size].c=c;
}

inline void init()
{
n=get_int(),c=get_int(),d1=get_int(),c1=get_int(),d2=get_int(),c2=get_int();
s=0,t=2*n+1;
for(int i=s;i<=t;i++) first[i]=-1;
for(int i=1;i<=n;i++)
{
x=get_int();
add(s,i,x,0),add(i,s,0,0);
add(n+i,t,x,0),add(t,n+i,0,0);
if(i+n+d1<=2*n) add(i,i+n+d1,inf,c1),add(i+n+d1,i,0,-c1);
if(i+n+d2<=2*n) add(i,i+n+d2,inf,c2),add(i+n+d2,i,0,-c2);
if(i<n) add(i,i+1,inf,0),add(i+1,i,0,0);
add(s,i+n,inf,c),add(i+n,s,0,-c);
}
}

inline bool spfa()
{
queue<int>q;
for(int i=s;i<=t;i++) dis[i]=inf,tmp[i]=first[i];
dis[s]=0,q.push(s),vis[s]=1;
while(q.size())
{
int p=q.front();q.pop();vis[p]=0;
for(register int u=first[p];~u;u=e[u].next)
{
int to=e[u].to;
if(!e[u].l || dis[to]<=dis[p]+e[u].c) continue;
dis[to]=dis[p]+e[u].c;
if(!vis[to]) q.push(to),vis[to]=1;
}
}
return dis[t]!=inf;
}

inline int dfs(int p,int flow)
{
if(p==t) return flow;
int s=0;vis[p]=1;
for(register int &u=tmp[p];~u;u=e[u].next)
{
int to=e[u].to;
if(vis[to] || dis[to]!=dis[p]+e[u].c || !e[u].l) continue;
int minn=dfs(to,min(flow-s,e[u].l));
s+=minn,e[u].l-=minn,e[u^1].l+=minn,sum+=minn*e[u].c;
if(s==flow) break;
}
vis[p]=0;
return s;
}

inline void solve()
{
while(spfa())
{while(x=dfs(s,inf));}
cout<<sum;
}

int main()
{
init();
solve();
return 0;
}