#6008. 「网络流 24 题」餐巾计划
题目描述
一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同。假设第 i ii 天需要 ri r_iri 块餐巾。餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分;或者把旧餐巾送到快洗部,洗一块需 M MM天,其费用为 F FF 分;或者送到慢洗部,洗一块需 N NN 天,其费用为 S SS 分(S<F S < FS<F)。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 n nn 天中餐巾使用计划,使总的花费最小。
输入格式
第 1 11 行有 6 66 个正整数 n nn、P PP、M MM、F FF、N NN、S SS。
n nn 是要安排餐巾使用计划的天数,P PP 是每块新餐巾的费用,M MM 是快洗部洗一块餐巾需用天数,F FF 是快洗部洗一块餐巾需要的费用,N NN 是慢洗部洗一块餐巾需用天数,S SS 是慢洗部洗一块餐巾需要的费用。
接下来的 n nn 行是餐厅在相继的 n nn 天里,每天需用的餐巾数。
输出格式
输出餐厅在相继的 n nn 天里使用餐巾的最小总花费。
样例
样例输入
3 10 2 3 3 2
5
6
7
样例输出
145
数据范围与提示
1≤n≤1000 1 \leq n \leq 10001≤n≤1000
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 const int N = 5010; 7 const int INF = 1e9; 8 9 struct Edge{ 10 int u,v,f,c,nxt; 11 Edge(){} 12 Edge(int a,int b,int flow,int cost,int nt) { //- 13 u = a;v = b;f = flow;c = cost;nxt = nt; 14 } 15 }e[100100]; 16 int head[N],dis[N],q[100100],pre[N]; 17 bool vis[N]; 18 int L,R,S,T,tot = 1,Mc,Mf; 19 20 inline char nc() { 21 static char buf[10010],*p1 = buf,*p2 = buf; 22 return p1==p2&&(p2=(p1=buf)+fread(buf,1,10000,stdin),p1==p2)?EOF:*p1++; 23 } 24 int read() { 25 int x = 0,f = 1;char ch = nc(); 26 for (; ch<'0'||ch>'9'; ch=nc()) if (ch=='-')f=-1; 27 for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0'; 28 return x*f; 29 } 30 void add_edge(int u,int v,int f,int c) { 31 e[++tot] = Edge(u,v,f,c,head[u]);head[u] = tot; 32 e[++tot] = Edge(v,u,0,-c,head[v]);head[v] = tot; 33 } 34 bool spfa() { 35 for (int i=1; i<=T; ++i) vis[i]=false,dis[i]=INF; 36 L = 1;R = 0; 37 dis[S] = 0; 38 q[++R] = S;vis[S] = true;pre[S] = 0; 39 while (L <= R) { 40 int u = q[L++]; 41 for (int i=head[u]; i; i=e[i].nxt) { 42 int v = e[i].v; 43 if (dis[v]>dis[u]+e[i].c && e[i].f > 0) { 44 dis[v] = dis[u] + e[i].c; 45 pre[v] = i; 46 if (!vis[v]) q[++R] = v,vis[v] = true; 47 } 48 } 49 vis[u] = false; 50 } 51 return dis[T]!=INF; 52 } 53 void mcf() { 54 int zf = INF; 55 for (int i=T; i!=S; i=e[pre[i]].u) 56 zf = min(zf,e[pre[i]].f); 57 for (int i=T; i!=S; i=e[pre[i]].u) 58 e[pre[i]].f -= zf,e[pre[i]^1].f += zf; 59 Mf += zf;Mc += dis[T]*zf; 60 } 61 int main() { 62 int n = read(),c = read(),kt = read(),kc = read(),mt = read(),mc = read(); 63 S = n*2+1;T = n*2+2; 64 for (int t,i=1; i<=n; ++i) { 65 t = read(); 66 add_edge(S,i,t,0); 67 add_edge(i+n,T,t,0); 68 add_edge(S,i+n,INF,c); 69 if (i+kt<=n) add_edge(i,i+n+kt,INF,kc); 70 if (i+mt<=n) add_edge(i,i+n+mt,INF,mc); 71 if (i+1<=n) add_edge(i,i+1,INF,0); 72 } 73 while (spfa()) mcf(); 74 printf("%d",Mc); 75 return 0; 76 }