【线性规划与网络流24题 10】餐巾计划

来源:互联网 发布:淘宝好评晒图怎么删掉 编辑:程序博客网 时间:2024/05/01 07:32

Description

一个餐厅在相继的N 天里,每天需用的餐巾数不尽相同。假设第i天需要ri块餐巾(i=1,2,…,N)。餐厅可以购买新的餐巾,每块餐巾的费用为p分;或者把旧餐巾送到快洗部,洗一块需m天,其费用为f 分;或者送到慢洗部,洗一块需n 天(n>m),其费用为s<f 分。 
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。 

试设计一个算法为餐厅合理地安排好N 天中餐巾使用计划,使总的花费最小。 

编程任务:编程找出一个最佳餐巾使用计划.

Input

第1 行有6 个正整数N,p,m,f,n,s。N 是要安排餐巾使用计划的天数;p 是每块新餐巾的费用;m 是快洗部洗一块餐巾需用天数;f 是快洗部洗一块餐巾需要的费用;n是慢洗部洗一块餐巾需用天数;s是慢洗部洗一块餐巾需要的费用。 
接下来的N 行是餐厅在相继的N 天里,每天需用的餐巾数。

Output

程序运行结束时,将餐厅在相继的N 天里使用餐巾的最小总花费输出

Sample Input

3 10 2 3 3 2567

Sample Output

145

Hint

题目中所有数字都不超过1000


【分析】

最大流最小费用

我们将每天视为一个点,考虑到每天有两种状态,取餐巾和用餐巾,我们将每天拆为两个点,i和i'。再建源点Sta,和汇点End。

建图方式如下:

1.源点到i,容量为需要的餐巾量,费用为0;

2.i'到汇点,容量为需要的餐巾量,费用为0;

3.源点到i',容量为INF,费用为p;

4.i到(i+m)',容量为INF,费用为f;

5.i到(i+n)',容量为INF,费用为s;

6.i到i+1,容量为INF,费用0;

1的意思是有这么多可以拿来洗。3的意思是买餐巾。

4,5的意思是拿去洗,而6的意思是干净的留给下一天。


【代码】

/****************************    ID:CiocioLANG:C++DATE:2013-12-23TASK:Network_flow 10****************************/#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <iostream>#include <algorithm>#include <queue>#include <vector>using namespace std;#define MAXN (1005*2)#define INF 0x7FFFFFFF#define p_b push_backint N,p,m,f,n,s,Sta,End;struct edge{int from,to,cap,flow,cost;edge(int a,int b,int c,int d,int f):from(a),to(b),cap(c),flow(d),cost(f){}};int Dis[MAXN],path[MAXN],fl[MAXN];bool inqueue[MAXN];vector <edge> edges;vector <int> g[MAXN];void _addedge(int from,int to,int cap,int cost){edges.p_b(edge(from,to,cap,0,cost));edges.p_b(edge(to,from,0,0,-cost));int m=edges.size();g[from].p_b(m-2);g[to].p_b(m-1);}void _read(int &x){char tt=getchar();while(tt<'0'||'9'<tt) tt=getchar();for(x=0;'0'<=tt&&tt<='9';x=(x<<3)+(x<<1)+tt-'0',tt=getchar());}void _init(){_read(N);_read(p);_read(m);_read(f);_read(n);_read(s);}queue <int> Q;bool _tryflow(int &flow,int &cost){for(int i=Sta;i<=End;i++) Dis[i]=INF;memset(inqueue,0,sizeof(inqueue));Dis[Sta]=0;inqueue[Sta]=true;path[Sta]=0;fl[Sta]=INF;while(!Q.empty()) Q.pop();Q.push(Sta);while(!Q.empty()){int u=Q.front();Q.pop();inqueue[u]=false;int sz=g[u].size();for(int j=0;j<sz;j++){edge &e=edges[g[u][j]];if(e.cap>e.flow&&Dis[e.to]>Dis[u]+e.cost){Dis[e.to]=Dis[u]+e.cost;path[e.to]=g[u][j];fl[e.to]=min(fl[u],e.cap-e.flow);if(!inqueue[e.to]){inqueue[e.to]=true;Q.push(e.to);}}}}if(Dis[End]==INF) return false;flow+=fl[End];cost+=fl[End]*Dis[End];int x=End;while(x!=Sta){edges[path[x]].flow+=fl[End];edges[path[x]^1].flow-=fl[End];x=edges[path[x]].from;}return true;}void _solve(){Sta=0;End=N*2+1;int need;for(int i=1;i<=N;i++){_read(need);_addedge(Sta,i,need,0);_addedge(i+N,End,need,0);_addedge(Sta,i+N,INF,p);if(i+m<=N) _addedge(i,i+N+m,INF,f);if(i+n<=N) _addedge(i,i+N+n,INF,s);if(i+1<=N) _addedge(i,i+1,INF,0);}int Maxflow,Mincost;Maxflow=Mincost=0;while(_tryflow(Maxflow,Mincost));cout<<Mincost<<endl;}int main(){_init();_solve();return 0;}


0 0
原创粉丝点击