[补档]餐巾

餐巾

题目

一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N)。餐厅可以从三种途径获得餐巾。
(1)购买新的餐巾,每块需p分;
(2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p)。如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此。
(3)把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f)。
在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部。在每天开始时,餐厅必须决定是否购买新餐巾及多少,使洗好的和新购的餐巾之和满足当天的需求量Ri,并使N天总的费用最小。

INPUT

输入文件共 3 行,第 1 行为总天数;
第 2 行为每天所需的餐巾块数;
第 3 行为每块餐巾的新购费用 p ,快洗所需天数 m ,快洗所需费用 f ,慢洗所需天数 n ,慢洗所需费用 s 。

OUTPUT

一行,最小的费用

SAMPLE

INPUT

3
3 2 4
10 1 6 2 3

OUTPUT

64

解题报告

首先,每天的餐巾分为两种情况,新买的和原来的。
每天作为一个点,由S向其连边,容量为Ri,花费为0。
每天可以向T连边,容量为INF,花费为p,每天都可以购买餐巾无数次。
将每天用过的餐巾在新建一层点,由于分配去快洗和慢洗的餐巾总数有限制,并非分别有限制,所有这两种无需再分开,这层点分别向T建边,容量为Ri,花费为0,限制总容量。
使用快洗的餐巾,由i向(i+m+N)’建边,容量为INF,花费为f,慢洗同理,花费分别建边。
但第i-m天洗完后的餐巾也可以供第i天以后使用。所以再由i向i+1建边,容量为INF,花费为0。这样第i天就能使用到以前所有可以使用的洗完的餐巾了。
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<queue>
 5 using namespace std;
 6 struct edge{
 7     int e,n,flow,cost;
 8 }a[20010];
 9 int pre[410],tot;
10 inline void insert(int s,int e,int flow,int cost){
11     a[tot].e=e;
12     a[tot].flow=flow;
13     a[tot].cost=cost;
14     a[tot].n=pre[s];
15     pre[s]=tot++;
16 }
17 int S(0),T;
18 int N,p,m,f,n,s;
19 int r[201];
20 int flow(0),ans(0),inf(0x7fffffff);
21 inline void build(){
22     for(int i=1;i<=N;i++){
23         insert(S,i,r[i],0),insert(i,S,0,0);
24         insert(S,i+N,inf,p),insert(i+N,S,0,-p);
25         insert(i+N,T,r[i],0),insert(T,i+N,0,0);
26         if(i+m<=N)
27             insert(i,i+m+N,inf,f),insert(i+m+N,i,0,-f);
28         if(i+n<=N)
29             insert(i,i+n+N,inf,s),insert(i+n+N,i,0,-s);
30         if(i!=N)
31             insert(i,i+1,inf,0),insert(i+1,i,0,0);
32     }
33 }
34 int dis[410],fa[410],path[410];
35 inline bool bfs(){
36     memset(dis,30,sizeof(dis));
37     memset(fa,-1,sizeof(fa));
38     queue<int>q;
39     q.push(S);
40     dis[S]=0;
41     while(!q.empty()){
42         int k(q.front());
43         q.pop();
44         for(int i=pre[k];i!=-1;i=a[i].n){
45             int e(a[i].e);
46             if(a[i].flow&&dis[e]>dis[k]+a[i].cost){
47                 dis[e]=dis[k]+a[i].cost;
48                 fa[e]=k;
49                 path[e]=i;
50                 q.push(e);
51             }
52         }
53     }
54     if(fa[T]==-1)
55         return false;
56     return true;
57 }
58 inline void dinic(){
59     while(bfs()){
60         int f(inf);
61         for(int i=T;i!=S;i=fa[i])
62             if(a[path[i]].flow<f)
63                 f=a[path[i]].flow;
64         flow+=f;
65         ans+=dis[T]*f;
66         for(int i=T;i!=S;i=fa[i]){
67             a[path[i]].flow-=f;
68             a[path[i]^1].flow+=f;
69         }
70     }
71 }
72 inline int gg(){
73     freopen("napkin.in","r",stdin);
74     freopen("napkin.out","w",stdout);
75     memset(pre,-1,sizeof(pre));
76     scanf("%d",&N);
77     T=(N<<1)+1;
78     for(int i=1;i<=N;i++)
79         scanf("%d",&r[i]);
80     scanf("%d%d%d%d%d",&p,&m,&f,&n,&s);
81     build();
82     dinic();
83     printf("%d",ans);
84     return 0;
85 }
86 int K(gg());
87 int main(){;}
View Code
原文地址:https://www.cnblogs.com/hzoi-mafia/p/7277693.html