1. 程式人生 > >【網路流24題】 No.10 餐巾計劃問題 (線性規劃網路優化 最小費用最大流)

【網路流24題】 No.10 餐巾計劃問題 (線性規劃網路優化 最小費用最大流)

【題意】

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

輸入檔案示例
input.txt
3 10 2 3 3 2
5
6
7

輸出檔案示例
output.txt
145

【分析】

  我建的圖真是又複雜又有問題,二分圖建法就很漂亮。(好吧只是類似二分圖,就是分成了兩個部分。。[%¥%&¥這是拆點吧。。)

把每天要用的和用完的分離開處理,建模後就是二分圖。二分圖X集合中頂點Xi表示第i天用完的餐巾,其數量為ri,所以從S向Xi連線容量為ri的邊作為限制。Y集合中每個點Yi則是第i天需要的餐巾,數量為ri,與T連線的邊容量作為限制。每天用完的餐巾可以選擇留到下一天(Xi->Xi+1),不需要花費,送到快洗部(Xi->Yi+m),費用為f,送到慢洗部(Xi->Yi+n),費用為s。每天需要的餐巾除了剛剛洗好的餐巾,還可能是新購買的(S->Yi),費用為p。

  好像可以三分??我不會。。。讓我找找三分題解。。。

  好吧看完了,不懂。。直接放連結了:

  %%%%% 這題是10^5 網路流過不了TAT 三分smg。。。 [他竟然單峰smg!!!

  關於線性規劃網路優化,一般是 有 : 決策變數 優化目標 約束 對應網路流的話 決策變數就是優化目標就是本題的費用 約束就是滿流限制

好像是這樣的吧 b.a..

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5
#include<algorithm> 6 #include<queue> 7 #include<cmath> 8 using namespace std; 9 #define Maxn 2010 10 #define INF 0xfffffff 11 12 struct node 13 { 14 int x,y,f,o,c,next; 15 }t[Maxn*1010];int len; 16 int first[Maxn]; 17 18 int mymin(int x,int y) {return x<y?x:y;} 19 int mymax(int x,int y) {return x>y?x:y;} 20 21 void ins(int x,int y,int f,int c) 22 { 23 t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c; 24 t[len].next=first[x];first[x]=len;t[len].o=len+1; 25 t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c; 26 t[len].next=first[y];first[y]=len;t[len].o=len-1; 27 } 28 29 int st,ed; 30 queue<int > q; 31 int dis[Maxn],pre[Maxn],flow[Maxn]; 32 bool inq[Maxn]; 33 bool bfs() 34 { 35 while(!q.empty()) q.pop(); 36 memset(dis,63,sizeof(dis)); 37 memset(inq,0,sizeof(inq)); 38 q.push(st);dis[st]=0;flow[st]=INF;inq[st]=1; 39 while(!q.empty()) 40 { 41 int x=q.front(); 42 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 43 { 44 int y=t[i].y; 45 if(dis[y]>dis[x]+t[i].c) 46 { 47 dis[y]=dis[x]+t[i].c; 48 pre[y]=i; 49 flow[y]=mymin(flow[x],t[i].f); 50 if(!inq[y]) 51 { 52 inq[y]=1; 53 q.push(y); 54 } 55 } 56 } 57 inq[x]=0;q.pop(); 58 } 59 if(dis[ed]>=INF-10000000) return 0; 60 return 1; 61 } 62 63 void output() 64 { 65 for(int i=1;i<=len;i+=2) 66 printf("%d->%d %d %d\n",t[i].x,t[i].y,t[i].f,t[i].c); 67 printf("\n"); 68 } 69 70 void max_flow() 71 { 72 int ans=0,sum=0; 73 while(bfs()) 74 { 75 sum+=dis[ed]*flow[ed]; 76 ans+=flow[ed]; 77 int now=ed; 78 while(now!=st) 79 { 80 t[pre[now]].f-=flow[ed]; 81 t[t[pre[now]].o].f+=flow[ed]; 82 now=t[pre[now]].x; 83 } 84 } 85 printf("%d\n",sum); 86 } 87 88 int nd[Maxn]; 89 int main() 90 { 91 int n,p,t1,w1,t2,w2; 92 scanf("%d%d%d%d%d%d",&n,&p,&t1,&w1,&t2,&w2); 93 for(int i=1;i<=n;i++) 94 { 95 scanf("%d",&nd[i]); 96 } 97 len=0; 98 memset(first,0,sizeof(first)); 99 st=2*n+1;ed=st+1; 100 for(int i=1;i<=n;i++) ins(st,i+n,INF,p); 101 for(int i=1;i<n;i++) ins(i,i+1,INF,0); 102 for(int i=1;i<=n-t1;i++) ins(i,i+t1+n,INF,w1); 103 for(int i=1;i<=n-t2;i++) ins(i,i+t2+n,INF,w2); 104 for(int i=1;i<=n;i++) ins(st,i,nd[i],0),ins(i+n,ed,nd[i],0); 105 max_flow(); 106 return 0; 107 }
View Code

2016-11-04 16:36:11