[HNOI 2001]软件开发
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
8 2 1 6
Sample Output
38
题解
经典构图题。
将每一天拆成两个点$i$,$i’$,
加如下$6$条边:
$(sta, i, ni, f)$——在第$i$天可以买至多$ni$个餐巾,每块$f$分;
$(i, fin, ni, 0)$——第$i$天要用$ni$块餐巾;
$(sta, i’, ni, 0)$——第$i$天用剩的$ni$块旧餐巾;
$(i’, i+a+1, ∞, fa)$——第$i$天的旧餐巾送到快洗部,每块$fa$分;
$(i’, i+b+1, ∞, fb)$——第$i$天的旧餐巾送到慢洗部,每块$fb$分;
$(i’, i’+1, ∞, 0)$——第$i$天的旧餐巾可以留到第$i+1$天再处理;
求一次最小费用流即为结果。
1 #include <set> 2 #include <map> 3 #include <ctime> 4 #include <cmath> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <cstdio> 9 #include <string> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 #define LL long long 15 #define Max(a, b) ((a) > (b) ? (a) : (b)) 16 #define Min(a, b) ((a) < (b) ? (a) : (b)) 17 using namespace std; 18 const int N = 2e3; 19 const int INF = ~0u>>1; 20 21 int n,a,b,f,fa,fb,ni; 22 struct tt{ 23 int to, cost, next, cap; 24 }edge[N*6+5]; 25 int path[N+5], top = -1; 26 void Add(int u, int v, int cap, int cost); 27 int sta, fin; 28 int min_cost_flow(); 29 int SPFA(); 30 31 int main(){ 32 memset(path, -1, sizeof(path)); 33 scanf("%d%d%d%d%d%d", &n, &a, &b, &f, &fa, &fb); 34 sta = 0, fin = 2*n+1; 35 for (int i = 1; i <= n; i++){ 36 scanf("%d", &ni); 37 Add(sta, i, ni, f); 38 Add(i, fin, ni, 0); 39 Add(sta, i+n, ni, 0); 40 if (i+a+1 <= n) Add(i+n, i+a+1, INF, fa); 41 if (i+b+1 <= n) Add(i+n, i+b+1, INF, fb); 42 if (i+1 <= n) Add(i+n, i+1+n, INF, 0); 43 } 44 printf("%d\n", min_cost_flow()); 45 return 0; 46 } 47 48 void Add(int u, int v, int cap, int cost){ 49 edge[++top].to = v; 50 edge[top].cost = cost; 51 edge[top].cap = cap; 52 edge[top].next = path[u]; 53 path[u] = top; 54 edge[++top].to = u; 55 edge[top].cost = -cost; 56 edge[top].cap = 0; 57 edge[top].next = path[v]; 58 path[v] = top; 59 } 60 int min_cost_flow(){ 61 int tolcost = 0; 62 int tmp; 63 while (tmp = SPFA()) tolcost += tmp; 64 return tolcost; 65 } 66 int SPFA(){ 67 int dist[N+5]; 68 memset(dist, 127/3, sizeof(dist)); dist[sta] = 0; dist[fin] = INF; 69 bool vis[N+5] = {0}; vis[sta] = 1; 70 queue<int>Q; 71 while (!Q.empty()) Q.pop(); 72 Q.push(sta); 73 int pre[N+5] = {0}; 74 while (!Q.empty()){ 75 int u = Q.front(); Q.pop(); vis[u]=0; 76 for (int i = path[u]; i != -1; i = edge[i].next){ 77 int v = edge[i].to; 78 if (dist[v] > dist[u]+edge[i].cost && edge[i].cap > 0){ 79 dist[v] = dist[u]+edge[i].cost; 80 pre[v] = i; 81 if (!vis[v]){ 82 vis[v] = 1; 83 Q.push(v); 84 } 85 } 86 } 87 } 88 if (dist[fin] == INF) return 0; 89 int minflow = INF; 90 for (int i = fin; i != sta; i = edge[pre[i]^1].to) 91 minflow = Min(minflow, edge[pre[i]].cap); 92 for (int i = fin; i != sta; i = edge[pre[i]^1].to) 93 edge[pre[i]].cap -= minflow, 94 edge[pre[i]^1].cap += minflow; 95 return dist[fin]*minflow; 96 }