1. 程式人生 > >【網絡流24題】1745: 餐巾計劃問題

【網絡流24題】1745: 餐巾計劃問題

flow 題解 tdi ++ 送去 sof ble col next

Description

一個餐廳在相繼的N 天裏,每天需用的餐巾數不盡相同。假設第i天需要ri塊餐巾(i=1, 2,…,N)。餐廳可以購買新的餐巾,每塊餐巾的費用為p分;或者把舊餐巾送到快洗部, 洗一塊需m天,其費用為f 分;或者送到慢洗部,洗一塊需n 天(n>m),其費用為s< f 分。 每天結束時,餐廳必須決定將多少塊臟的餐巾送到快洗部,多少塊餐巾送到慢洗部,以及多 少塊保存起來延期送洗。但是每天洗好的餐巾和購買的新餐巾數之和,要滿足當天的需求量。 試設計一個算法為餐廳合理地安排好N 天中餐巾使用計劃,使總的花費最小。 編程任務: 編程找出一個最佳餐巾使用計劃.

Input

由文件input.txt提供輸入數據。文件第1 行有6 個正整數N,p,m,f,n,s。N 是要安排餐巾 使用計劃的天數;p 是每塊新餐巾的費用;m 是快洗部洗一塊餐巾需用天數;f 是快洗部洗 一塊餐巾需要的費用;n是慢洗部洗一塊餐巾需用天數;s是慢洗部洗一塊餐巾需要的費用。 接下來的N 行是餐廳在相繼的N 天裏,每天需用的餐巾數。

Output

程序運行結束時,將餐廳在相繼的N 天裏使用餐巾的最小總花費輸出到文件output.txt 中。

Sample Input

3 10 2 3 3 2 5 6 7 Sample Output 145 此題困擾我很久,發個題解來總結:
剛開始在想怎麽做到既流滿當天的流又流到其他天去。設n為總天數,然後(s,i,inf,p)(i,i+n,ri,0)(i,i+n+m,INF,f)(i+n,T,INF,0)發現跑spfa會跑錯答案 然後就隨之想到題解的做法: (s,i+n,ri,p)這是購買當天的 (s,i,ri,0)(i,i+n+m,INF,f)(i,i+n+sn,INF,s)這是模擬送去快洗部和滿洗部 註意洗完後的餐巾不一定就要送到i+n+m,大於等於i+n+m皆可,所以連邊(i,i+1,INF,0).表示洗完的餐巾當天不用,流向下一天 (傻逼的我居然把i到>=n+m+i的都建了邊,然後TLE了) (i+n,T,ri,0)相當於限制當天的總餐具數
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 const int N=2005,INF=1999999999;
 8 int gi(){
 9     int str=0;char ch=getchar();
10     while(ch>9 || ch<0)ch=getchar();
11     while(ch>=0 && ch<=9)str=str*10+ch-0,ch=getchar();
12     return str;
13 }
14 int n,s,sn,p,F,fn,T,S=0,ans=0;
15 int num=1,head[N],f[N],vis[N],q[N*10],pre[N];
16 struct Lin{
17     int next,to,dis,cost;
18 }a[1000001];
19 void init(int x,int y,int z,int cost){
20     a[++num].next=head[x];
21     a[num].to=y;
22     a[num].dis=z;
23     a[num].cost=cost;
24     head[x]=num;
25     a[++num].next=head[y];
26     a[num].to=x;
27     a[num].dis=0;
28     a[num].cost=-cost;
29     head[y]=num;
30 }
31 void Change()
32 {
33     int x=T,flow=INF;
34     while(x){
35         flow=min(flow,a[pre[x]].dis);
36         x=a[pre[x]^1].to;
37     }
38     x=T;
39     while(x){
40         a[pre[x]].dis-=flow;
41         a[pre[x]^1].dis+=flow;
42         ans+=a[pre[x]].cost*flow;
43         x=a[pre[x]^1].to;
44     }
45 }
46 bool spfa()
47 {
48     for(int i=0;i<=T;i++)f[i]=INF,vis[i]=false;
49     int t=0,sum=1,x,u;
50     q[1]=S;f[S]=0;vis[S]=true;
51     while(t!=sum)
52     {
53         x=q[++t];
54         for(int i=head[x];i;i=a[i].next)
55         {
56             if(a[i].dis<=0)continue;
57             u=a[i].to;
58             if(f[x]+a[i].cost<f[u])
59             {
60                 f[u]=f[x]+a[i].cost;
61                 pre[u]=i;
62                 if(!vis[u])vis[u]=true,q[++sum]=u;
63             }
64         }
65         vis[x]=false;
66     }
67     return f[T]!=INF;
68 }
69 int main()
70 {
71     //freopen("pp.in","r",stdin);
72     int x;
73     n=gi();p=gi();fn=gi();F=gi();sn=gi();s=gi();T=(n<<1)+1;
74     for(int i=1;i<=n;i++){
75         x=gi();
76         init(S,i,x,0);
77         init(i+n,T,x,0);
78         init(S,i+n,x,p);
79         if(i<n)init(i,i+1,INF,0);
80         if(i+fn<=n)init(i,i+n+fn,INF,F);
81         if(i+sn<=n)init(i,i+n+sn,INF,s);
82     }
83     while(spfa())Change();
84     printf("%d",ans);
85     return 0;
86 }

【網絡流24題】1745: 餐巾計劃問題