最小费用最大流。
每天拆成两个点,早上和晚上;
晚上可以获得(r_i)条脏毛巾,从源点连一条容量为(r_i),费用为0的边。
早上要供应(r_i)条毛巾,连向汇点一条容量为(r_i)吗,费用为0的边。
每天可以买毛巾,晚上向第二天早上连一条费用为(p),容量为(inf)的边。
可以送快洗,晚上向(m)天之后的早上连费用(f),容量(inf)的边
可以送慢洗,晚上向(n)天之后的早上连费用(s),容量(inf)的边
脏毛巾可以留到第二天晚上,源点向第二天晚上连一条容量(r_i),费用0的边。
最后跑费用流即可。
常数巨大的代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
}
inline void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar((x%10)^48);
}
inline void write(int x) {if(!x) putchar('0');else print(x);putchar('
');}
#define maxn 1000050
int n,m,s,t,max_flow,tot=1,min_cost;
int head[maxn],dis[maxn],vis[maxn],v[70][70];
struct edge{int to,nxt,w,c;}e[maxn<<1];
void add(int u,int v,int w,int c) {e[++tot]=(edge){v,head[u],w,c},head[u]=tot;}
void ins(int u,int v,int w,int c) {add(u,v,w,c),add(v,u,0,-c);}
int spfa() {
memset(vis,0,sizeof vis);
memset(dis,63,sizeof dis);
queue<int > q;q.push(s);dis[s]=0;vis[s]=1;
while(!q.empty()) {
int now=q.front();q.pop();vis[now]=0;
for(int i=head[now];i;i=e[i].nxt)
if(e[i].w>0&&dis[e[i].to]>dis[now]+e[i].c) {
dis[e[i].to]=dis[now]+e[i].c;
if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
}
}return dis[t]<1e9;
}
int dfs(int u,int f) {
if(u==t) {max_flow+=f,min_cost+=f*dis[t],vis[t]=1;return f;}
vis[u]=1;int used=0;
for(int i=head[u];i;i=e[i].nxt)
if(e[i].w>0&&dis[e[i].to]==dis[u]+e[i].c&&!vis[e[i].to]) {
int flow=dfs(e[i].to,min(f-used,e[i].w));
if(flow>0) {e[i].w-=flow,e[i^1].w+=flow;return flow;}
if(used==f) break;
}
return used;
}
void cost_flow() {
while(spfa()) {
vis[t]=1;
while(vis[t]) memset(vis,0,sizeof vis),dfs(s,1e9);
}
}
signed main() {
read(n);int x;s=0,t=n*2+1;
for(int i=1;i<=n;i++) read(x),ins(s,i,x,0),ins(i+n,t,x,0);
int p,m,f,nn,ss;read(p),read(m),read(f),read(nn),read(ss);
for(int i=1;i<=n;i++) {
ins(s,i+n,1e7,p);
if(i+m<=n) ins(i,i+m+n,1e7,f);
if(i+nn<=n) ins(i,i+nn+n,1e7,ss);
if(i+1<=n) ins(i,i+1,1e7,0);
}cost_flow();write(min_cost);
return 0;
}