zoukankan      html  css  js  c++  java
  • 线性规划与网络流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费用流
  • 相关阅读:
    小问题收集
    JSON.NET与LINQ序列化示例教程
    前台页面中json和字符串相互转化
    jQuery Validate (1)
    jQuery Validate (摘自官网)
    SQL基础(八)-- sql左右连接中的on and 和 on where 的区别
    SQL基础(七)--or和in的使用
    SQL基础(六)--RaiseError的用法
    C#基础(三)--Sort排序
    C#中Equals和==的区别 (面试官经常会问到)
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3621345.html
Copyright © 2011-2022 走看看