一个餐厅在相继的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; }
原文:http://www.cnblogs.com/wsy01/p/7932123.html