题目描述 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和Ci表示,每天的需求用day[i]表示

从s向Ci连容量为day[i]费用为0的边,表示有这么多毛巾用完

从s向Ri连容量为无穷大费用为p的边,表示每天都可以买毛巾

从Ri向t连容量为day[i]费用为0的边,表示每天必须用这么多毛巾

从Ci向Ri+m连容量为无穷费用为f的边,表示第i天用完的毛巾送入快洗部i+m天的时候可以用了,慢洗也一样

从Ri向Ri+1连容量为无穷大费用为0的边,表示第i天没用完,i+1天继续用

 

  1 const
  2     maxn=800;
  3 var
  4     map,w:array[0..maxn*2,0..maxn*2]of longint;
  5     first,next,last:array[0..maxn*maxn*2]of longint;
  6     n,p,k,fk,m,fm,tot,ans:longint;
  7 
  8 procedure insert(x,y:longint);
  9 begin
 10     inc(tot);
 11     last[tot]:=y;
 12     next[tot]:=first[x];
 13     first[x]:=tot;
 14 end;
 15 
 16 procedure init;
 17 var
 18     i,j:longint;
 19 begin
 20     read(n,p,k,fk,m,fm);
 21     insert(0,1+maxn);
 22     map[0,1+maxn]:=maxlongint;
 23     w[0,1+maxn]:=p;
 24     for i:=1 to n do
 25       begin
 26         read(map[0,i]);
 27         map[i+maxn,n+maxn+1]:=map[0,i];
 28         insert(0,i);
 29         insert(i+maxn,n+maxn+1);
 30       end;
 31     for i:=1 to n-1 do
 32       begin
 33         insert(i+maxn,i+maxn+1);
 34         insert(i+maxn+1,i+maxn);
 35         map[i+maxn,i+maxn+1]:=maxlongint;
 36       end;
 37     for i:=1 to n do
 38       begin
 39         if i+m<=n then
 40         begin
 41           insert(i,i+m+maxn);
 42           insert(i+m+maxn,i);
 43           map[i,i+m+maxn]:=maxlongint;
 44           w[i,i+m+maxn]:=fm;
 45           w[i+m+maxn,i]:=-fm;
 46         end;
 47         if (k<>m)and(i+k<=n) then
 48         begin
 49           insert(i,i+k+maxn);
 50           insert(i+k+maxn,i);
 51           map[i,i+k+maxn]:=maxlongint;
 52           w[i,i+k+maxn]:=fk;
 53           w[i+k+maxn,i]:=-fk;
 54         end;
 55       end;
 56 end;
 57 
 58 var
 59     d,dis,pre:array[0..maxn*2]of longint;
 60     flag:array[0..maxn*2]of boolean;
 61     head,num,tail:longint;
 62 
 63 function spfa:boolean;
 64 var
 65     i:longint;
 66 begin
 67     head:=1;
 68     tail:=1;
 69     num:=1;
 70     d[1]:=0;
 71     dis[0]:=0;
 72     dis[n+maxn+1]:=maxlongint;
 73     for i:=1 to n do
 74       begin
 75         dis[i]:=maxlongint;
 76         dis[i+maxn]:=maxlongint;
 77       end;
 78     while num>0 do
 79       begin
 80         i:=first[d[head]];
 81         while i<>0 do
 82           begin
 83             if map[d[head],last[i]]>0 then
 84             if dis[last[i]]>dis[d[head]]+w[d[head],last[i]] then
 85             begin
 86               pre[last[i]]:=d[head];
 87               dis[last[i]]:=dis[d[head]]+w[d[head],last[i]];
 88               if flag[last[i]]=false then
 89               begin
 90                 flag[last[i]]:=true;
 91                 tail:=tail mod(n*2+2)+1;
 92                 d[tail]:=last[i];
 93                 inc(num);
 94               end;
 95             end;
 96             i:=next[i];
 97           end;
 98         flag[d[head]]:=false;
 99         head:=head mod (n*2+2)+1;
100         dec(num);
101       end;
102     if dis[n+maxn+1]<>maxlongint then exit(true);
103     exit(false);
104 end;
105 
106 function min(x,y:longint):longint;
107 begin
108     if x<y then exit(x);
109     exit(y);
110 end;
111 
112 procedure work;
113 var
114     i,flow:longint;
115 begin
116     while spfa do
117       begin
118         flow:=maxlongint;
119         i:=n+maxn+1;
120         while i<>0 do
121           begin
122             flow:=min(flow,map[pre[i],i]);
123             i:=pre[i];
124           end;
125         i:=n+maxn+1;
126         inc(ans,flow*dis[n+maxn+1]);
127         while i<>0 do
128           begin
129             dec(map[pre[i],i],flow);
130             inc(map[i,pre[i]],flow);
131             i:=pre[i];
132           end;
133       end;
134     write(ans);
135 end;
136 
137 begin
138     init;
139     work;
140 end.
SPFA费用流

相关文章:

  • 2021-10-23
  • 2021-05-27
  • 2021-06-15
  • 2022-01-09
  • 2021-06-05
  • 2021-08-17
  • 2021-10-18
  • 2021-06-28
猜你喜欢
  • 2021-10-15
  • 2022-12-23
  • 2021-05-19
  • 2021-12-07
  • 2022-12-23
  • 2021-07-31
相关资源
相似解决方案