题目描述
一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N)。餐厅可以从三种途径获得餐巾。
(1)购买新的餐巾,每块需p分;
(2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p)。如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此。
(3)把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f)。
在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部。在每天开始时,餐厅必须决定是否购买新餐巾及多少,使洗好的和新购的餐巾之和满足当天的需求量Ri,并使N天总的费用最小
输入输出格式
输入格式:
输入文件共3行,第1行为总天数;第2行为每天所需的餐巾块数;第3行为每块餐巾的新购费用p,快洗所需天数m,快洗所需费用f,慢洗所需天数n,慢洗所需费用s。
输出格式:
输出文件共1行为最小的费用。
输入输出样例
说明
N<=2000
ri<=10000000
p,f,s<=10000
时限4s
学习了一下zkw费用流,大概就是用dinic跑费用流,,快的飞起
建图还很麻烦。把每天拆成ai,bi两点,ai表示用过的,bi没用过。建立超级源汇S,T。
(1)S向ai连容量r[i],费用0的边,S向bi连容量r[i],费用p的边
(2)bi向T连容量r[i],费用0的边
(3)ai向b(i+m)连容量无穷,费用f的边,ai向b(i+n)连容量无穷,费用f的边,ai向a(i+1)连容量无穷费用0的边
然后zkw 50ms过了
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
#define N 2005
using namespace std;
int day,n,m,p,s,f,S,T,tot,r[N],cur[N<<1],hd[N<<1],vis[N<<1],d[N<<1];
ll cost;
struct edge{int u,v,w,next,cap,flow;}e[N<<4];
void adde(int u,int v,int w,int c){
e[tot].u=u;
e[tot].v=v;
e[tot].w=w;
e[tot].cap=c;
e[tot].next=hd[u];
hd[u]=tot++;
}
bool spfa(){
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
deque<int>q;d[T]=0;q.push_back(T);
while(!q.empty()){
int u=q.front();q.pop_front();vis[u]=0;
for(int i=hd[u];~i;i=e[i].next){
if(e[i^1].cap<=e[i^1].flow)continue;
int w=e[i^1].w,v=e[i].v;
if(d[v]>d[u]+w){
d[v]=d[u]+w;
if(vis[v])continue;
vis[v]=1;
if(!q.empty()&&d[v]<d[q.front()])q.push_front(v);
else q.push_back(v);
}
}
}
return d[S]<0x3f3f3f3f;
}
int dfs(int u,int a){
if(!a||u==T)return a;
vis[u]=1;int f=0,fl=0;
for(int &i=cur[u];~i;i=e[i].next){
int v=e[i].v;
if(d[v]+e[i].w==d[u]&&!vis[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
cost+=(ll)f*e[i].w;fl+=f;
e[i].flow+=f;
e[i^1].flow-=f;
a-=f;
if(!a)break;
}
}
vis[u]=0;return fl;
}
int main(){
#ifdef wsy
freopen("data.in","r",stdin);
#else
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
#endif
memset(hd,-1,sizeof(hd));
scanf("%d",&day);S=0;T=(day<<1)+1;
for(int i=1;i<=day;i++)scanf("%d",&r[i]);
scanf("%d%d%d%d%d",&p,&m,&f,&n,&s);
for(register int i=1;i<=day;i++){
adde(S,i,0,r[i]);adde(i,S,0,0);
adde(S,i+day,p,inf);adde(i+day,S,-p,0);
if(i!=day)adde(i,i+1,0,inf),adde(i+1,i,0,0);
adde(i+day,T,0,r[i]);adde(T,i+day,0,0);
if(i+m<=day)adde(i,i+day+m,f,inf),adde(i+day+m,i,-f,0);
if(i+n<=day)adde(i,i+day+n,s,inf),adde(i+day+n,i,-s,0);
}
while(spfa()){
for(int i=S;i<=T;i++)cur[i]=hd[i];
dfs(S,inf);
}
printf("%lld",cost);
return 0;
}