1237 餐巾计划问题
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同。假设第 i 天需要 ri块餐巾(i=1,2,…,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s<f 分。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。
编程找出一个最佳餐巾使用计划.
输入描述
Input Description
第 1 行有 6 个正整数 N,p,m,f,n,s。N 是要安排餐巾使用计划的天数;p 是每块新餐巾的费用;m 是快洗部洗一块餐巾需用天数;f 是快洗部洗一块餐巾需要的费用;n 是慢洗部洗一块餐巾需用天数;s 是慢洗部洗一块餐巾需要的费用。接下来的 N 行是餐厅在相继的 N 天里,每天需用的餐巾数。
输出描述
Output Description
将餐厅在相继的 N 天里使用餐巾的最小总花费输出
样例输入
Sample Input
3 10 2 3 3 2
5
6
7
样例输出
Sample Output
145
数据范围及提示
Data Size & Hint
N<=2000
ri<=10000000
p,f,s<=10000
时限4s
题解
最小费用最大流。
把每天拆成两个点,脏毛巾(1~N)和干净毛巾(N+1~2N),
从源点往每个干净毛巾的点连一条费用为p,流量INF的边;(买新毛巾
每个干净点往汇点连费用为0,流量ri的边(提供干净毛巾
从源点往每个脏毛巾点连费用为0,流量ri的边(给处理的人脏毛巾
每个脏点往m天后的干净点连费用为f,流量INF的边(让快洗部洗
同理往n天后的干净点连费用为s,流量INF的边(让慢洗部洗
以及,每个脏点往下一个脏点连费用为0,流量INF(留着不洗
最后跑一遍从S到T的费用流,输出最小费用。
1 #include<queue> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 using namespace std; 7 const int INF=999999999; 8 int n,fx,tk,fk,tm,fm; 9 int s,t; 10 struct emm{ 11 int e,f,v,c; 12 }a[300007]; 13 int h[2007]; 14 int tot=1; 15 void con(int l,int r,int vv,int cc) 16 { 17 a[++tot].f=h[l]; 18 h[l]=tot; 19 a[tot].e=r; 20 a[tot].v=vv; 21 a[tot].c=cc; 22 a[++tot].f=h[r]; 23 h[r]=tot; 24 a[tot].e=l; 25 a[tot].c=-cc; 26 return; 27 } 28 int d[2007]; 29 bool sf[2007]; 30 queue<int>q; 31 inline bool spfa() 32 { 33 memset(sf,0,sizeof(sf)); 34 memset(d,127,sizeof(d)); 35 d[s]=0;sf[s]=1;q.push(s); 36 while(!q.empty()) 37 { 38 int x=q.front();q.pop(); 39 for(int i=h[x];i;i=a[i].f) 40 if(d[x]+a[i].c<d[a[i].e]&&a[i].v) 41 { 42 d[a[i].e]=d[x]+a[i].c; 43 if(!sf[a[i].e]) 44 { 45 sf[a[i].e]=1; 46 q.push(a[i].e); 47 } 48 } 49 sf[x]=0; 50 } 51 return d[t]<INF; 52 } 53 unsigned long long ans=0; 54 int dfs(int x,int al) 55 { 56 sf[x]=1; 57 if(x==t||!al)return al; 58 int fl=0; 59 for(int i=h[x];i;i=a[i].f) 60 if(d[a[i].e]==d[x]+a[i].c&&a[i].v&&!sf[a[i].e]) 61 { 62 int f=dfs(a[i].e,min(al,a[i].v)); 63 if(f) 64 { 65 fl+=f; 66 al-=f; 67 ans+=f*a[i].c; 68 a[i].v-=f; 69 a[i^1].v+=f; 70 if(!al)break; 71 } 72 } 73 if(!fl)d[x]=-INF; 74 return fl; 75 } 76 void scan() 77 { 78 scanf("%d%d%d%d%d%d",&n,&fx,&tk,&fk,&tm,&fm); 79 s=0,t=2*n+1; 80 for(int i=1;i<=n;++i) 81 { 82 int ri; 83 scanf("%d",&ri); 84 con(s,i,ri,0); 85 con(s,i+n,INF,fx); 86 con(i+n,t,ri,0); 87 if(i<n)con(i,i+1,INF,0); 88 if(i+tm<=n)con(i,i+tm+n,INF,fm); 89 if(i+tk<=n)con(i,i+tk+n,INF,fk); 90 } 91 return; 92 } 93 void zkw() 94 { 95 while(spfa()) 96 { 97 sf[t]=1; 98 while(sf[t]) 99 { 100 memset(sf,0,sizeof(sf)); 101 dfs(s,INF); 102 } 103 } 104 return; 105 } 106 int main() 107 { 108 scan(); 109 zkw(); 110 cout<<ans; 111 return 0; 112 }