线性规划与网络流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和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费用流

不过spfa跑这种图有点吃力,用zkw就很快了(这个在wikioi上基本是超时,运气好第10个点992ms,用前向星+记录类型时间就差不多是这个的一半,懒得写记录类型了)

  1 const

  2     maxn=800;

  3     maxlongint=100000000;

  4 var

  5     map,w:array[0..maxn*2,0..maxn*2]of longint;

  6     first,next,last:array[0..maxn*maxn*2]of longint;

  7     n,p,k,fk,m,fm,tot,ans:longint;

  8 

  9 procedure insert(x,y:longint);

 10 begin

 11     inc(tot);

 12     last[tot]:=y;

 13     next[tot]:=first[x];

 14     first[x]:=tot;

 15 end;

 16 

 17 procedure init;

 18 var

 19     i:longint;

 20 begin

 21     read(n,p,k,fk,m,fm);

 22     for i:=1 to n do

 23       begin

 24         read(map[0,i]);

 25         map[i+maxn,n+maxn+1]:=map[0,i];

 26         insert(0,i);

 27         insert(i+maxn,n+maxn+1);

 28       end;

 29     for i:=1 to n-1 do

 30       begin

 31         insert(i,i+1);

 32         insert(i+1,i);

 33         map[i,i+1]:=maxlongint;

 34       end;

 35     for i:=1 to n do

 36       begin

 37         insert(0,i+maxn);

 38         map[0,i+maxn]:=maxlongint;

 39         w[0,i+maxn]:=p;

 40         if i+m<=n then

 41         begin

 42           insert(i,i+m+maxn);

 43           insert(i+m+maxn,i);

 44           map[i,i+m+maxn]:=maxlongint;

 45           w[i,i+m+maxn]:=fm;

 46           w[i+m+maxn,i]:=-fm;

 47         end;

 48         if (k<>m)and(i+k<=n) then

 49         begin

 50           insert(i,i+k+maxn);

 51           insert(i+k+maxn,i);

 52           map[i,i+k+maxn]:=maxlongint;

 53           w[i,i+k+maxn]:=fk;

 54           w[i+k+maxn,i]:=-fk;

 55         end;

 56       end;

 57 end;

 58 

 59 var

 60     dis,f,vis:array[0..maxn*2]of longint;

 61     time,flow:longint;

 62 

 63 function dfs(x,flow:longint):longint;

 64 var

 65     i,min,d:longint;

 66 begin

 67     if x=n+maxn+1 then

 68     begin

 69         inc(ans,flow*dis[n+maxn+1]);

 70         exit(flow);

 71     end;

 72     vis[x]:=time;

 73     i:=first[x];

 74     dfs:=0;

 75     while i<>0 do

 76       begin

 77         d:=dis[x]+w[x,last[i]]-dis[last[i]];

 78         min:=flow;

 79         if map[x,last[i]]<min then min:=map[x,last[i]];

 80         if (min>0)and(f[last[i]]>d) then f[last[i]]:=d;

 81         if (min>0)and(d=0)and(vis[last[i]]<>time) then

 82         begin

 83           d:=dfs(last[i],min);

 84           inc(dfs,d);

 85           dec(flow,d);

 86           dec(map[x,last[i]],d);

 87           inc(map[last[i],x],d);

 88         end;

 89         if flow=0 then break;

 90         i:=next[i];

 91       end;

 92 end;

 93 

 94 procedure work;

 95 var

 96     i,imp:longint;

 97 begin

 98     repeat

 99       inc(time);

100       for i:=1 to n do

101         begin

102           f[i]:=maxlongint;

103           f[i+maxn]:=maxlongint;

104         end;

105       f[0]:=maxlongint;

106       f[n+maxn+1]:=maxlongint;

107       inc(flow,dfs(0,maxlongint));

108       imp:=maxlongint;

109       for i:=1 to n do

110         begin

111           if (vis[i]<>time) and (f[i]<imp) then imp:=f[i];

112           if (vis[i+maxn]<>time) and (f[i+maxn]<imp) then imp:=f[i+maxn];

113         end;

114       if (vis[n+maxn+1]<>time) and (f[n+maxn+1]<imp) then imp:=f[n+maxn+1];

115       if imp=maxlongint then break;

116       for i:=1 to n do

117         begin

118           if vis[i]<>time then inc(dis[i],imp);

119           if vis[i+maxn]<>time then inc(dis[i+maxn],imp);

120         end;

121       if vis[n+maxn+1]<>time then inc(dis[n+maxn+1],imp);

122     until false;

123     write(ans);

124 end;

125 

126 begin

127     init;

128     work;

129 end.
zkw费用流

 

你可能感兴趣的:(网络流)