网路流24题-10
来源:互联网 发布:cf卡数据恢复公司 编辑:程序博客网 时间:2024/06/08 15:21
餐巾计划问题
«问题描述:
一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同。假设第 i 天需要 r i 块餐巾(i=1,
2,…,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,
洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s < f 分。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多
少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。
«编程任务:
编程找出一个最佳餐巾使用计划.
«数据输入:
由文件 input.txt 提供输入数据。文件第 1 行有 6 个正整数 N,p,m,f,n,s。N 是要安排餐巾
使用计划的天数;p 是每块新餐巾的费用;m 是快洗部洗一块餐巾需用天数;f 是快洗部洗
一块餐巾需要的费用;n 是慢洗部洗一块餐巾需用天数;s 是慢洗部洗一块餐巾需要的费用。
接下来的 N 行是餐厅在相继的 N 天里,每天需用的餐巾数。
«结果输出:
程序运行结束时,将餐厅在相继的 N 天里使用餐巾的最小总花费输出到文件 output.txt
中。
输入文件示例
input.txt
3 10 2 3 3 2
5
6
7
输出文件示例
output.txt
145
【问题分析】
网络优化问题,用最小费用最大流解决。
【建模方法】
把每天分为二分图两个集合中的顶点Xi,Yi,建立附加源S汇T。
1、从S向每个Xi连一条容量为ri,费用为0的有向边。
2、从每个Yi向T连一条容量为ri,费用为0的有向边。
3、从S向每个Yi连一条容量为无穷大,费用为p的有向边。
4、从每个Xi向Xi+1(i+1<=N)连一条容量为无穷大,费用为0的有向边。
5、从每个Xi向Yi+m(i+m<=N)连一条容量为无穷大,费用为f的有向边。
6、从每个Xi向Yi+n(i+n<=N)连一条容量为无穷大,费用为s的有向边。
求网络最小费用最大流,费用流值就是要求的最小总花费。
【建模分析】
这个问题的主要约束条件是每天的餐巾够用,而餐巾的来源可能是最新购买,也可能是前几天送洗,今天刚刚洗好的餐巾。每天用完的餐巾可以选择送到快洗部或慢洗部,或者留到下一天再处理。
经过分析可以把每天要用的和用完的分离开处理,建模后就是二分图。二分图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。
在网络上求出的最小费用最大流,满足了问题的约束条件(因为在这个图上最大流一定可以使与T连接的边全部满流,其他边只要有可行流就满足条件),而且还可以保证总费用最小,就是我们的优化目标。
个人理解:图论模型中,约束限制条件可以用边表示,状态转移是边的方向,点是对象。
此处纸巾的去处就是具体的哪一天,一天到一天的的不同途径也就是不同边的花费,容量没有限制,但用完的可以转移到下一天
#include<iostream>#include<math.h>#include<cstring>#include<algorithm>#include<set>#include<map>#include<queue>#include<cstdio>#include<vector>const int INF=0x7fffffff;const int maxn=4001;using namespace std;struct edge{ int to,cap,cost,rev;};int V;int N,p,m,f,n,s,S,T,mincost,Ans=0;vector<edge> G[maxn];int dist[maxn];int prevv[maxn];int preve[maxn];void add_edge(int from,int to,int cap,int cost){ G[from].push_back((edge){to,cap,cost,G[to].size()}); G[to].push_back((edge){from,0,-cost,G[from].size()-1});}int min_cost_flow(int s,int t,int f){ int res=0; while(f>0) { fill(dist,dist+V,INF); dist[s]=0; bool update=true; while(update) { update=false; for(int v=0;v<V;v++) { if(dist[v]==INF) continue; for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&dist[e.to]>dist[v]+e.cost) { dist[e.to]=dist[v]+e.cost; prevv[e.to]=v; preve[e.to]=i; update=true; } } } } if(dist[t]==INF) return -1; int d=f; for(int v=t;v!=s;v=prevv[v]) d=min(d,G[prevv[v]][preve[v]].cap); f-=d; res+=d*dist[t]; for(int v=t;v!=s;v=prevv[v]) { edge &e=G[prevv[v]][prevv[v]]; e.cap-=d; G[v][e.rev].cap+=d; } } return res;}void init(){ cin>>N>>p>>m>>f>>n>>s; V=2*N+2; S=0; T=2*N+1; for(int i=1;i<=N;i++) { int x; cin>>x; Ans+=x; add_edge(S,i,x,0); add_edge(i+N,T,x,0); add_edge(S,i+N,INF,p); } for(int i=1;i+1<=N;i++) { add_edge(i,i+1,INF,0); } for(int i=1;i+m<=N;i++) { add_edge(i,i+N+m,INF,f); } for(int i=1;i+n<=N;i++) add_edge(i,i+n+N,INF,s);}void solve(){ mincost=min_cost_flow(S,T,Ans); cout<<mincost<<endl;}int main(){ init(); solve(); return 0;}
- 网路流24题-10
- 增广路求网路最大流
- StaggeredGridView+universal-image-loader加载网路图片实现瀑布流
- StaggeredGridView+universal-image-loader加载网路图片实现瀑布流
- 网路指令:
- 网路命令
- 网路编程
- 网路编程
- 网路连接
- 网路MTU
- 网路协议
- 网路协议
- hdu 3987 Harry Potter and the Forbidden Forest【网路流最小割模型】
- hdoj 2732 Leapin' Lizards 【拆点网路流】 【题目数据坑。。。】
- 文件流输出到本地内存/直接访问外网路径,等到返回值
- 选择一个网路邻居
- 网路摘抄【1】
- 网路摘抄【2】
- C#winform实现锁屏功能
- 常用Openssl命令
- 小错误统计
- 验证哥德巴赫猜想(范围不大)
- html初学笔记6
- 网路流24题-10
- 去除点击元素后的高亮效果。
- Ubuntu14.04,openjdk8 cacerts的丢失
- 初学 require.js(一)
- C++ primer 学习笔记
- Analyzing Crash Reports——分析崩溃报告之一
- Ubuntu 14.04 LTS Apache2 开启 SSI 功能
- Vue2.0史上最全入坑教程(上)—— 搭建Vue脚手架(vue-cli)
- python安装pywin32问题