一个餐厅在相继的 NNN 天里,每天需用的餐巾数不尽相同。假设第 iii 天需要 rir_iri块餐巾( i=1,2,…,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 ppp 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 nnn 天(n>mn>mn>m),其费用为 sss 分(s<fs<fs<f)、
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 NNN 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。
这个题目是一个费用流的题目
首先我们要把每一天拆成早上和晚上两个点
连边如下:
- 晚上从起点获得x条脏餐巾,从原点向每一天晚上连一条流量为当天所用餐巾x,费用为0的边。
- 白天向汇点提供x条干净的餐巾,从每一天早上向汇点连一条流量为当天所用餐巾x,费用为0的边 。
- 晚上可以将脏餐巾留到第二天晚上,从每一天晚上向第二天晚上连一条流量为INF,费用为0的边
- 晚上可以送去快洗部,在地i+t1天早上收到餐巾 ,从每一天晚上向这一天+快洗所用天数t1的那一天早上连一条流量为INF,费用为快洗所用钱数的边
- 晚上可以送去慢洗部,在地i+t2天早上收到餐巾 ,从每一天晚上向这一天+慢洗所用天数t2的那一天早上连一条流量为INF,费用为慢洗所用钱数的边
- 每天早上可以购买餐巾,从起点向每一天早上连一条流量为INF,费用为购买餐巾所用钱数的边
建好了图之后,就可以直接套上费用流的模板跑最大流了
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define re register
#define gc getchar()
#define ll long long
#define il inline
il ll read() {
re ll x(0),f(1);
re char ch=gc;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=gc;
}
while(ch>='0'&&ch<='9') {
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
return x*f;
}
inline ll min(ll a,ll b) {
return a<b?a:b;
}
const ll INF=(1<<29),N=100010;
struct node {
ll to,next,w,c;
} e[N];
ll h[N],cnt=1,n,s,t;
inline void add(ll u,ll v,ll w,ll c) {
e[++cnt]=(node) {v,h[u],w,c},h[u]=cnt;
e[++cnt]=(node) {u,h[v],0,-c},h[v]=cnt;
}
#define QXX(u) for(ll i=h[u],y;y=e[i].to,i;i=e[i].next)
ll dis[N],vis[N],pre[N],f[N],maxf,minc,m;
ll spfa() {
for(ll i=1; i<=t; ++i) dis[i]=INF,vis[i]=0;
std::queue<ll> q;
while(!q.empty()) q.pop();
q.push(s);
vis[s]=1,dis[s]=0,pre[t]=-1,f[s]=INF;
while(!q.empty()) {
ll x=q.front();
q.pop();
vis[x]=0;
QXX(x) {
if(!e[i].w) continue;
if(dis[y]>dis[x]+e[i].c) {
dis[y]=dis[x]+e[i].c;
f[y]=min(f[x],e[i].w);
pre[y]=i;
if(!vis[y]) vis[y]=1,q.push(y);
}
}
}
return pre[t]==-1?-1:f[t];
}
void dinic () {
ll x,in,y;
while ((in=spfa ())!=-1) {
x=t;
while (x!=s) {
y=pre[x];
e[y].w-=in;
e[y^1].w+=in;
x=e[y^1].to;
}
maxf+=in;
minc+=in*dis[t];
}
cout<<minc<<endl;
}
int main() {
scanf("%d",&n);
s=0,t=2*n+1;
for(ll i=1; i<=n; i++) {
ll x=read();
add(s,i,x,0);
add(i+n,t,x,0);
}
ll m=read(),t1=read(),m1=read(),t2=read(),m2=read();
for(ll i=1; i<=n; i++) {
if(i+1<=n) add(i,i+1,INF,0);
if(i+t1<=n) add(i,i+n+t1,INF,m1);
if(i+t2<=n) add(i,i+n+t2,INF,m2);
add(s,i+n,INF,m);
}
dinic();
return 0;
}