餐巾
题目
一个餐厅在相继的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天总的费用最小。INPUT
输入文件共 3 行,第 1 行为总天数;第 2 行为每天所需的餐巾块数;第 3 行为每块餐巾的新购费用 p ,快洗所需天数 m ,快洗所需费用 f ,慢洗所需天数 n ,慢洗所需费用 s 。OUTPUT
一行,最小的费用SAMPLE
INPUT
33 2 410 1 6 2 3OUTPUT
64
解题报告
首先,每天的餐巾分为两种情况,新买的和原来的。
每天作为一个点,由S向其连边,容量为Ri,花费为0。
每天可以向T连边,容量为INF,花费为p,每天都可以购买餐巾无数次。
将每天用过的餐巾在新建一层点,由于分配去快洗和慢洗的餐巾总数有限制,并非分别有限制,所有这两种无需再分开,这层点分别向T建边,容量为Ri,花费为0,限制总容量。
使用快洗的餐巾,由i向(i+m+N)’建边,容量为INF,花费为f,慢洗同理,花费分别建边。
但第i-m天洗完后的餐巾也可以供第i天以后使用。所以再由i向i+1建边,容量为INF,花费为0。这样第i天就能使用到以前所有可以使用的洗完的餐巾了。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 using namespace std; 6 struct edge{ 7 int e,n,flow,cost; 8 }a[20010]; 9 int pre[410],tot; 10 inline void insert(int s,int e,int flow,int cost){ 11 a[tot].e=e; 12 a[tot].flow=flow; 13 a[tot].cost=cost; 14 a[tot].n=pre[s]; 15 pre[s]=tot++; 16 } 17 int S(0),T; 18 int N,p,m,f,n,s; 19 int r[201]; 20 int flow(0),ans(0),inf(0x7fffffff); 21 inline void build(){ 22 for(int i=1;i<=N;i++){ 23 insert(S,i,r[i],0),insert(i,S,0,0); 24 insert(S,i+N,inf,p),insert(i+N,S,0,-p); 25 insert(i+N,T,r[i],0),insert(T,i+N,0,0); 26 if(i+m<=N) 27 insert(i,i+m+N,inf,f),insert(i+m+N,i,0,-f); 28 if(i+n<=N) 29 insert(i,i+n+N,inf,s),insert(i+n+N,i,0,-s); 30 if(i!=N) 31 insert(i,i+1,inf,0),insert(i+1,i,0,0); 32 } 33 } 34 int dis[410],fa[410],path[410]; 35 inline bool bfs(){ 36 memset(dis,30,sizeof(dis)); 37 memset(fa,-1,sizeof(fa)); 38 queue<int>q; 39 q.push(S); 40 dis[S]=0; 41 while(!q.empty()){ 42 int k(q.front()); 43 q.pop(); 44 for(int i=pre[k];i!=-1;i=a[i].n){ 45 int e(a[i].e); 46 if(a[i].flow&&dis[e]>dis[k]+a[i].cost){ 47 dis[e]=dis[k]+a[i].cost; 48 fa[e]=k; 49 path[e]=i; 50 q.push(e); 51 } 52 } 53 } 54 if(fa[T]==-1) 55 return false; 56 return true; 57 } 58 inline void dinic(){ 59 while(bfs()){ 60 int f(inf); 61 for(int i=T;i!=S;i=fa[i]) 62 if(a[path[i]].flow<f) 63 f=a[path[i]].flow; 64 flow+=f; 65 ans+=dis[T]*f; 66 for(int i=T;i!=S;i=fa[i]){ 67 a[path[i]].flow-=f; 68 a[path[i]^1].flow+=f; 69 } 70 } 71 } 72 inline int gg(){ 73 freopen("napkin.in","r",stdin); 74 freopen("napkin.out","w",stdout); 75 memset(pre,-1,sizeof(pre)); 76 scanf("%d",&N); 77 T=(N<<1)+1; 78 for(int i=1;i<=N;i++) 79 scanf("%d",&r[i]); 80 scanf("%d%d%d%d%d",&p,&m,&f,&n,&s); 81 build(); 82 dinic(); 83 printf("%d",ans); 84 return 0; 85 } 86 int K(gg()); 87 int main(){;}