[網絡流24題] 餐巾
[網絡流24題] 餐巾
時間限制:5 s 內存限制:128 MB
【問題描述】
一個餐廳在相繼的N天裏,第i天需要Ri塊餐巾(i=l,2,…,N)。餐廳可以從三種途徑獲得餐巾。
(1)購買新的餐巾,每塊需p分;
(2)把用過的餐巾送到快洗部,洗一塊需m天,費用需f分(f<p)。如m=l時,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情況也如此。
(3)把餐巾送到慢洗部,洗一塊需n天(n>m),費用需s分(s<f)。
在每天結束時,餐廳必須決定多少塊用過的餐巾送到快洗部,多少塊送慢洗部。在每天開始時,餐廳必須決定是否購買新餐巾及多少,使洗好的和新購的餐巾之和滿足當天的需求量Ri,並使N天總的費用最小。
【輸入】
輸入文件共 3 行,第 1 行為總天數;第 2 行為每天所需的餐巾塊數;第 3 行為每塊餐巾的新購費用 p ,快洗所需天數 m ,快洗所需費用 f ,慢洗所需天數 n ,慢洗所需費用 s 。
【輸出】
一行,最小的費用
【樣例】
napkin.in
3
3 2 4
10 1 6 2 3
napkin.out
64
【數據規模】
n<=200,Ri<=50
還是要看題解才能寫...
我們約定餐巾洗好之後當天就用,這樣臟餐巾可以放幾天再去洗。
我們將每一天看做兩個點,對於第i天,拆成i<<1和i<<1|1,第一個點表示當天需要的餐巾,第二個點表示截止目前剩下的臟餐巾。
那麽將s與每一個i<<1連邊,流量大小為a[i],權值為p,再將i<<1連向t,流量為a[i],權值為0,這種情況下求得最大流時的費用便是每天的餐巾都新買的費用。
再講s與i<<1|1連一條邊,流量也為a[i],權值為0,表示當天用完餐巾會產生的臟餐巾,再把i<<1|1向(i+1)<<1|1連邊,表示當天的臟餐巾可以留到第二天再洗,流量為inf,權值為0,對於兩種洗餐巾,將i<<1|1,連向(i+d1)<<1,表示當天洗完的餐巾可以留給那一天用,流量為inf,權值為c1。跑一遍zkw即可。
1 #include<bits/stdc++.h> 2View Codeusing namespace std; 3 const int maxn=420; 4 const int inf=0x3fffffff; 5 int n,a[maxn],p,d1,c1,d2,c2; 6 int tot=-1,fi[maxn],next[maxn<<4],to[maxn<<4],cost[maxn<<4],flow[maxn<<4]; 7 int s,t,ans,que[maxn],head,tail,cur[maxn],dis[maxn],vis[maxn]; 8 void edge_add(int x,int y,int f,int c){ 9 to[++tot]=y;next[tot]=fi[x];fi[x]=tot;cost[tot]=c;flow[tot]=f; 10 to[++tot]=x;next[tot]=fi[y];fi[y]=tot;cost[tot]=-c;flow[tot]=0; 11 } 12 bool bfs(){ 13 head=tail=1; 14 que[++tail]=s; 15 for(int i=s;i<=t;i++)cur[i]=fi[i],dis[i]=inf,vis[i]=0; 16 dis[s]=0; 17 vis[s]=1; 18 while(head!=tail){ 19 head++; 20 if(head==410)head=1; 21 int u=que[head]; 22 vis[u]=0; 23 for(int i=fi[u];i+1;i=next[i]){ 24 if(flow[i]&&dis[to[i]]>dis[u]+cost[i]){ 25 dis[to[i]]=dis[u]+cost[i]; 26 if(!vis[to[i]]){ 27 vis[to[i]]=1; 28 tail++; 29 if(tail==410)tail=1; 30 que[tail]=to[i]; 31 } 32 } 33 } 34 } 35 return dis[t]!=inf; 36 } 37 int dfs(int x,int f){ 38 vis[x]=1; 39 if(x==t||!f)return f; 40 for(int i=cur[x];i+1;i=next[i]){ 41 cur[x]=i; 42 if(!vis[to[i]]&&flow[i]&&dis[to[i]]==dis[x]+cost[i]){ 43 int g=dfs(to[i],min(f,flow[i])); 44 if(g){//cout<<x<<" "<<g<<endl; 45 ans+=g*cost[i]; 46 flow[i]-=g; 47 flow[i^1]+=g; 48 return g; 49 } 50 } 51 } 52 return 0; 53 } 54 void zkw(){ 55 while(bfs()) 56 while(dfs(s,inf)); 57 printf("%d\n",ans); 58 } 59 int main() 60 { 61 scanf("%d",&n); 62 s=1;t=n*2+2; 63 memset(fi,-1,sizeof(fi)); 64 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 65 scanf("%d%d%d%d%d",&p,&d1,&c1,&d2,&c2); 66 for(int i=1;i<=n;i++){ 67 edge_add(s,i<<1,a[i],p); 68 edge_add(i<<1,t,a[i],0); 69 edge_add(s,i<<1|1,a[i],0); 70 if(i!=n)edge_add(i<<1|1,(i+1)<<1|1,inf,0); 71 if(i+d1<=n)edge_add(i<<1|1,(i+d1)<<1,inf,c1); 72 if(i+d2<=n)edge_add(i<<1|1,(i+d2)<<1,inf,c2); 73 } 74 zkw(); 75 return 0; 76 }
[網絡流24題] 餐巾