「网络流24题」餐巾计划问题

Posted real_l

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「网络流24题」餐巾计划问题相关的知识,希望对你有一定的参考价值。

题目描述 Description

一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同。假设第 i 天需要 ri块餐巾(i=1,2,…,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s<f 分。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。
编程找出一个最佳餐巾使用计划.

输入描述 Input Description

第 1 行有 6 个正整数 N,p,m,f,n,s。N 是要安排餐巾使用计划的天数;p 是每块新餐巾的费用;m 是快洗部洗一块餐巾需用天数;f 是快洗部洗一块餐巾需要的费用;n 是慢洗部洗一块餐巾需用天数;s 是慢洗部洗一块餐巾需要的费用。接下来的 N 行是餐厅在相继的 N 天里,每天需用的餐巾数。

输出描述 Output Description

将餐厅在相继的 N 天里使用餐巾的最小总花费输出

样例输入 Sample Input

3 10 2 3 3 2

5

6

7

样例输出 Sample Output

145

 题目分析

  此题用最小费用流解决  

  题目所说的每天需用ri块餐巾,我们可以这么理解,把一天拆成两个点Xi和Yi(上午和下午),一天既然需要用ri块餐巾,则必定会消耗ri块,所以我们把Xi表示为这一天接受到的干净的餐巾数,Yi表示为消耗的餐巾数,那么就好建边了.

  从Xi-->X(i+1)建一条(inf,0)的边,表示此边容量无穷大,费用为0,理解为前一天可以把没用完的餐巾留到后一天

  从源点S-->每个Xi建一条(inf,p)的边,表示无论如何你至少可以通过买餐巾来达到需求

  从源点S-->每个Yi建一条(ri,0)的边

  从每个Xi-->汇点T点建一条(ri,0)的边

  从每个Yi-->X(i+m)建一条(inf,f)的边表示每天可以送餐巾到快洗部,费用为f

  同理从每个Yi-->X(i+n)建一条(inf,s)的边表示每天可以送餐巾到慢洗部,费用为s

  然后直接跑费用流模板

  上代码

  

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<string>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<cstdlib>
  8 #include<queue>
  9 #define in(i) (i=read())
 10 #define inf (2147483647)
 11 using namespace std;
 12 typedef long long lol;//就是要注意一点因为最大值赋的是int类型最大值,所以有乘法运算就会爆int,so开long long
 13 lol read()
 14 {
 15   lol ans=0,f=1;
 16   char i=getchar();
 17   while(i<0||i>9)
 18     {
 19       if(i==-) f=-1;
 20       i=getchar();
 21     }
 22   while(i>=0&&i<=9)
 23     {
 24       ans=(ans<<3)+(ans<<1)+i-0;
 25       i=getchar();
 26     }
 27   return ans*f;
 28 }
 29 struct edge
 30 {
 31   lol to,next,cap,v;
 32 }e[40010];
 33 lol head[40010];
 34 lol lev[4010],vis[4010];
 35 lol len=1;
 36 void add(lol a,lol b,lol c,lol d)
 37 {
 38   e[++len].to=b;
 39   e[len].next=head[a];
 40   e[len].cap=c;
 41   e[len].v=d;
 42   head[a]=len;
 43 }
 44 lol pre[3010];
 45 bool bfs(lol s,lol t)
 46 {
 47   queue<lol>q;
 48   memset(lev,127/3,sizeof(lev));
 49   q.push(s);
 50   lev[s]=0;
 51   while(!q.empty())
 52     {
 53       lol x=q.front();
 54       q.pop();
 55       for(lol i=head[x];i;i=e[i].next)
 56     {
 57       lol to=e[i].to;
 58       if(e[i].cap>0&&lev[to]>lev[x]+e[i].v)
 59         {
 60           lev[to]=lev[x]+e[i].v;
 61           pre[to]=i;
 62           q.push(to);
 63         }
 64     }
 65     }
 66   if(lev[t]<lev[0]) return 1;
 67   return 0;
 68 }
 69 lol change(lol s,lol t)
 70 {
 71   lol x=t,flow=inf,ans=0;
 72   while(x!=s)
 73     {
 74       flow=min(flow,e[pre[x]].cap);
 75       x=e[pre[x]^1].to;
 76     }
 77   x=t;
 78   while(x!=s)
 79     {
 80       e[pre[x]].cap-=flow;
 81       e[pre[x]^1].cap+=flow;
 82       ans+=flow*e[pre[x]].v;
 83       x=e[pre[x]^1].to;
 84     }
 85   return ans;
 86 }
 87 int main()
 88 {
 89   lol tot=0;
 90   lol n,r;
 91   lol p,a,f,b,s;
 92   in(n);
 93   for(lol i=1;i<=n;i++)
 94     {
 95       in(r);
 96       add(i,(n<<1)+2,r,0);//Xi-->T
 97       add((n<<1)+2,i,0,0);
 98       add((n<<1)+1,i+n,r,0);//S-->Yi
 99       add(i+n,(n<<1)+1,0,0);
100     }
101   in(p);
102   for(lol i=1;i<=n;i++)
103     {
104       add((n<<1)+1,i,inf,p);//S-->Xi,买餐巾
105       add(i,(n<<1)+1,0,-p);
106     }
107   for(lol i=1;i<n;i++)
108     {
109       add(i,i+1,inf,0);//前一天留到第二天
110       add(i+1,i,0,0);
111     }
112   in(a);in(f);
113   for(lol i=1;i<=n-a;i++)
114     {
115       add(i+n,i+a,inf,f);//送到快洗部
116       add(i+a,i+n,0,-f);
117     }
118   in(b);in(s);
119   for(lol i=1;i<=n-b;i++)
120     {
121       add(i+n,i+b,inf,s);//送到慢洗部
122       add(i+b,i+n,0,-s);
123     }
124   while(bfs((n<<1)+1,(n<<1)+2))
125     {
126       tot+=change((n<<1)+1,(n<<1)+2);
127     }
128   cout<<tot<<endl;
129   return 0;
130 }

 

以上是关于「网络流24题」餐巾计划问题的主要内容,如果未能解决你的问题,请参考以下文章

网络流24题餐巾计划问题(最小费用最大流)

网络流24题- 餐巾计划问题

[网络流24题] 餐巾计划问题

网络流24题餐巾计划(图解)

[网络流24题]餐巾计划问题

「网络流24题」餐巾计划问题