软件开发
Time Limit: 10 Sec Memory Limit: 162 MB
[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.
Output
最少费用
Sample Input
8 2 1 6
Sample Output
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
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ;
const int EDG = ;
const int INF = ; 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=,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
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]=; w[tot]=-z;
} bool Bfs()
{
for(int i=S;i<=T;i++) dist[i] = INF;
dist[S] = ; vis[S] = ;
tou = ; wei = ; q[] = 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] = ;
q[++wei] = v;
}
}
}
vis[u] = ;
}
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-)^)+] += x;
Ans += x*w[e];
}
} int main()
{
n=get(); a=get(); b=get();
f=get(); fA=get(); fB=get();
S=; T=n*+;
for(int i=;i<=n;i++) X[i]=i, Y[i]=i+n;
for(int i=;i<=n;i++)
{
x = get();
Add(S,X[i], x,);
Add(Y[i],T, x,);
Add(S,Y[i], INF,f);
if(i!=n) Add(X[i],X[i+], INF,);
if(Y[i]+a+ < T)Add(X[i],Y[i]+a+, INF,fA);
if(Y[i]+b+ < T)Add(X[i],Y[i]+b+, INF,fB);
} while(Bfs()) Deal();
printf("%d",Ans); }