软件开发
Time Limit: 10 Sec Memory Limit: 162 MB
Description
某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。
第1行为n,a,b,f,fA,fB. 第2行为n1,n2,……,nn.
Output
最少费用
4 1 2 3 2 1
8 2 1 6
Sample Output
38
HINT
1≤f,fA,fB≤60,1≤n≤1000
Main idea
每天要用Ni块餐巾,有如下几种选择:
1.买新的,每块f元;
2.用A方式处理,a天后得到餐巾,每块花费fA元;
3.用B方式处理,b天后得到餐巾,每块花费fB元。
问满足要求的最小花费。
Solution
显然是费用流,拆成两个点,Xi表示用完的,Yi表示需要的,那么建模显然:(令x表示这天需要多少餐巾)
S->Xi 流量为x,费用为0 , mean:这天需要这么多 ;
Yi->T 流量为x,费用为0 , mean:这天需要这么多 ;
S->Yi 流量为INF,费用为f , mean:全部买新的 ;
Xi->Xi+1 流量为INF,费用为0 , mean:把这天用完的餐巾放到下一天处理 ;
Xi->Yi+a+1 流量为INF,费用为fA , mean:用A方式处理 ;
Xi->Yi+b+1 流量为INF,费用为fB , mean:用B方式处理 。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include <bits/stdc++.h> using namespace std;typedef long long s64;const int ONE = 1000001 ;const int EDG = 1000001 ;const int INF = 2147483640 ;int n,a,b,f,fA,fB;int x;int X[ONE],Y[ONE];int S,T;int next[EDG],first[ONE],go[EDG],from[EDG],pas[EDG],w[EDG],tot;int dist[ONE],pre[ONE],vis[ONE];int tou,wei,q[ONE];int Ans;inline int get () { int res=1 ,Q=1 ; char c; while ( (c=getchar ())<48 || c>57 ) if (c=='-' )Q=-1 ; if (Q) res=c-48 ; while ((c=getchar ())>=48 && c<=57 ) res=res*10 +c-48 ; return res*Q; } void Add (int u,int v,int flow,int z) { next[++tot]=first[u]; first[u]=tot; go[tot]=v; from[tot]=u; pas[tot]=flow; w[tot]=z; next[++tot]=first[v]; first[v]=tot; go[tot]=u; from[tot]=v; pas[tot]=0 ; w[tot]=-z; } bool Bfs () { for (int i=S;i<=T;i++) dist[i] = INF; dist[S] = 0 ; vis[S] = 1 ; tou = 0 ; wei = 1 ; q[1 ] = S; while (tou < wei) { int u = q[++tou]; for (int e=first[u]; e; e=next[e]) { int v = go[e]; if (dist[v] > dist[u] + w[e] && pas[e]) { dist[v] = dist[u] + w[e]; pre[v] = e; if (!vis[v]) { vis[v] = 1 ; q[++wei] = v; } } } vis[u] = 0 ; } return dist[T] != INF; } void Deal () { int x = INF; for (int e=pre[T]; e; e=pre[from[e]]) x = min (x,pas[e]); for (int e=pre[T]; e; e=pre[from[e]]) { pas[e] -= x; pas[((e-1 )^1 )+1 ] += x; Ans += x*w[e]; } } int main () { n=get (); a=get (); b=get (); f=get (); fA=get (); fB=get (); S=0 ; T=n*2 +5 ; for (int i=1 ;i<=n;i++) X[i]=i, Y[i]=i+n; for (int i=1 ;i<=n;i++) { x = get (); Add (S,X[i], x,0 ); Add (Y[i],T, x,0 ); Add (S,Y[i], INF,f); if (i!=n) Add (X[i],X[i+1 ], INF,0 ); if (Y[i]+a+1 < T)Add (X[i],Y[i]+a+1 , INF,fA); if (Y[i]+b+1 < T)Add (X[i],Y[i]+b+1 , INF,fB); } while (Bfs ()) Deal (); printf ("%d" ,Ans); }