1221: [HNOI2001] 软件开发
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1428 Solved: 791
[Submit][Status][Discuss]
Description
某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。
Input
第1行为n,a,b,f,fA,fB. 第2行为n1,n2,……,nn. (注:1≤f,fA,fB≤60,1≤n≤1000)
Output
最少费用
Sample Input
4 1 2 3 2 1
8 2 1 6
8 2 1 6
Sample Output
38
HINT
Source
最小费用最大流,各种调代码。
把每一天拆点,分为Xi和Yi。可以理解X为未消毒,Y为已消毒。
源点向Xi供应Ni个费用为0的流量,代表每天产生的用过的毛巾。
Yi向汇点连容量Ni的费用为0的边,代表每天使用的毛巾。
源点向Yi连费用为F的边,容量无穷,代表可以新购毛巾。
Xi向Yi+A+1连费用为Fa的边,代表可以在i时送去消毒,i+A+1时使用;B同理。
Xi向Xi+1连边,代表今天的脏毛巾可以留着回头再拿来洗。
1 #include <bits/stdc++.h> 2 3 inline int get_c(void) 4 { 5 static const int siz = 1024; 6 7 static char buf[siz]; 8 static char *head = buf + siz; 9 static char *tail = buf + siz; 10 11 if (head == tail) 12 fread(head = buf, 1, siz, stdin); 13 14 return *head++; 15 } 16 17 inline int get_i(void) 18 { 19 register int ret = 0; 20 register int neg = false; 21 register int bit = get_c(); 22 23 for (; bit < 48; bit = get_c()) 24 if (bit == '-')neg ^= true; 25 26 for (; bit > 47; bit = get_c()) 27 ret = ret * 10 + bit - 48; 28 29 return neg ? -ret : ret; 30 } 31 32 const int inf = 2e9; 33 const int maxn = 200005; 34 35 int n, a, b, f, c, d; 36 37 int s, t; 38 int edges; 39 int hd[maxn]; 40 int to[maxn]; 41 int fl[maxn]; 42 int vl[maxn]; 43 int nt[maxn]; 44 45 inline void add(int u, int v, int f, int w) { 46 nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; vl[edges] = +w; hd[u] = edges++; 47 nt[edges] = hd[v]; to[edges] = u; fl[edges] = 0; vl[edges] = -w; hd[v] = edges++; 48 } 49 50 int dis[maxn]; 51 int pre[maxn]; 52 53 inline bool bfs(void) { 54 static int que[maxn]; 55 static int inq[maxn]; 56 static int head, tail; 57 58 for (int i = s; i <= t; ++i)dis[i] = inf; 59 memset(inq, 0, sizeof(inq)); 60 que[tail++] = s; 61 pre[s] = -1; 62 dis[s] = 0; 63 inq[s] = 1; 64 65 while (head != tail) { 66 int u = que[head++], v; inq[u] = 0; 67 if (head == maxn)head = 0; 68 for (int i = hd[u]; ~i; i = nt[i]) 69 if (fl[i] && dis[v = to[i]] > dis[u] + vl[i]) { 70 dis[v] = dis[u] + vl[i]; 71 pre[v] = i ^ 1; 72 if (!inq[v]) { 73 inq[que[tail++] = v]; 74 if (tail == maxn) 75 tail = 0; 76 } 77 } 78 } 79 80 return dis[t] < inf; 81 } 82 83 inline int minCost(void) { 84 int cost = 0; 85 86 while (bfs()) { 87 int flow = inf; 88 89 for (int i = pre[t]; ~i; i = pre[to[i]]) 90 flow = std::min(flow, fl[i ^ 1]); 91 92 for (int i = pre[t]; ~i; i = pre[to[i]]) 93 fl[i] += flow, fl[i ^ 1] -= flow; 94 95 cost += flow * dis[t]; 96 } 97 98 return cost; 99 } 100 101 signed main(void) 102 { 103 memset(hd, -1, sizeof(hd)); 104 105 n = get_i(); 106 a = get_i(); 107 b = get_i(); 108 f = get_i(); 109 c = get_i(); 110 d = get_i(); 111 112 s = 0, t = (n + 1) * 2 + 1; 113 114 for (int i = 1; i <= n; ++i) { 115 int x = get_i(); 116 add(s, i, x, 0); 117 add(i + n, t, x, 0); 118 add(s, i + n, inf, f); 119 if (i + 1 <= n) 120 add(i, i + 1, inf, 0); 121 if (i + a + 1 <= n) 122 add(i, i + a + 1 + n, inf, c); 123 if (i + b + 1 <= n) 124 add(i, i + b + 1 + n, inf, d); 125 } 126 127 printf("%d ", minCost()); 128 }
@Author: YouSiki