[HNOI2001]软件开发
题目描述
某软件公司正在规划一项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. (注:1≤f,fA,fB≤60,1≤n≤1000)
输出格式:最少费用
输入输出样例
输入样例#1:
复制
4 1 2 3 2 1 8 2 1 6
输出样例#1: 复制
38
建立附加源点和汇点S和T
1. 源点到第i天的入点连容量ni费用为0的边
2. 第i天的出点到汇点连容量ni费用为0的边
3. 源点到第i天的出点连容量为INF费用为f的边
4. 第i天的入点到第i+a+1(i+b+1)天的出点连容量为INF费用为fa(fb)的边
5. 第i天的入点到第i+1天的入点连容量为INF费用为0的边
S连出的边表示这一天会剩下ni个脏布,连向T表示这一天要用ni个布
一天用完的ni个布,可以由a(b)方式给第i+a+1(i+b+1)天,也可以不洗,留到下一天再洗
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 struct Node 8 { 9 int next,to,c,dis,u; 10 }edge[200001]; 11 int num=1,head[5001],inf=2e9,dis[5001],pre[5001]; 12 long long ans; 13 int d[5001],n,a,b,fa,fb,f; 14 bool vis[5001]; 15 void add(int u,int v,int c,int d) 16 { 17 num++; 18 edge[num].next=head[u]; 19 head[u]=num; 20 edge[num].to=v; 21 edge[num].dis=d; 22 edge[num].c=c; 23 edge[num].u=u; 24 num++; 25 edge[num].next=head[v]; 26 head[v]=num; 27 edge[num].to=u; 28 edge[num].dis=-d; 29 edge[num].c=0; 30 edge[num].u=v; 31 } 32 bool SPFA() 33 {int INF,i; 34 memset(pre,-1,sizeof(pre)); 35 memset(vis,0,sizeof(vis)); 36 memset(dis,127/3,sizeof(dis)); 37 INF=dis[0]; 38 dis[0]=0; 39 queue<int>Q; 40 Q.push(0); 41 while (Q.empty()==0) 42 { 43 int u=Q.front(); 44 Q.pop(); 45 vis[u]=0; 46 for (i=head[u];i;i=edge[i].next) 47 { 48 int v=edge[i].to; 49 if (edge[i].c&&dis[v]>dis[u]+edge[i].dis) 50 { 51 dis[v]=dis[u]+edge[i].dis; 52 pre[v]=i; 53 if (vis[v]==0) 54 { 55 vis[v]=1; 56 Q.push(v); 57 } 58 } 59 } 60 } 61 if (dis[2*n+1]==INF) return 0; 62 return 1; 63 } 64 void change() 65 {int i; 66 int T=2*n+1; 67 int minf=inf; 68 for (i=pre[T];i!=-1;i=pre[edge[i].u]) 69 { 70 minf=min(minf,edge[i].c); 71 } 72 for (i=pre[T];i!=-1;i=pre[edge[i].u]) 73 { 74 edge[i].c-=minf; 75 edge[i^1].c+=minf; 76 } 77 ans+=minf*dis[T]; 78 } 79 int main() 80 {int i; 81 cin>>n>>a>>b>>f>>fa>>fb; 82 for (i=1;i<=n;i++) 83 scanf("%d",&d[i]); 84 for (i=1;i<=n;i++) 85 add(0,i,d[i],0),add(i+n,2*n+1,d[i],0),add(0,i+n,inf,f); 86 for (i=1;i<=n-1;i++) 87 add(i,i+1,inf,0); 88 for (i=1;i<=n;i++) 89 { 90 if (i+a+1<=n) add(i,i+a+1+n,inf,fa); 91 if (i+b+1<=n) add(i,i+b+1+n,inf,fb); 92 } 93 while (SPFA()) change(); 94 cout<<ans; 95 }