网络流二十四题之十 —— 餐巾计划问题(NAPK)
2016-05-16 21:32
351 查看
餐巾计划问题
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 天里使用餐巾的最小总花费输出Solution
本题要把握的一点,就是每天生产出来的脏餐巾是固定的——即每天需用的餐斤数。这样,我们就可以这样构图:
我们将使用餐巾和生产脏餐巾分为两个不同的板块。
因为限制条件为每天需要用一定数目的餐巾,所以在“使用餐巾”这个版块中,我们将每一天都连一条容量为每天需用的餐巾数的边到汇点。
从源点向“生产脏餐巾”的板块提供原料:从源点向每天连一条容量为每天需用的餐巾数的边。
生产出脏餐巾后,连一条容量为无限的边到送往快洗部洗完之后的那一天,费用设置为快洗的费用;连一条容量为无限的边到送往慢洗部洗完之后的那一天,费用设置为慢洗的费用。
另外,可以当天的餐巾不洗,留到第二天或永远不洗,那么我们还需要从每一天向其之后的那一天连一条容量为无限,费用为 0 的边。
最后求最小费用最大流即可。
因为是最大流,所以除了容量为无限的边之外,其它的边均为满流,满足题目条件。
Code
[cpp]#include <iostream>#include <cstdio>
#include <cstring>
#include <queue>
#define Min(x,y) ((x)<(y)?(x):(y))
#define MAXN 1000010
#define MAXE 100010
#define INF 0x3f3f3f3f
#define ss 0
#define tt 100005
using namespace std;
int N,p,m,f,n,s,ans;
int cnt;
int nxt[MAXN],data[MAXN],wei[MAXN],flow[MAXN],from[MAXN];
int head[MAXE],dis[MAXE];
int pre[MAXE];
bool in_stack[MAXE];
queue<int>q;
void add(int x,int y,int a,int b){
from[cnt]=x;nxt[cnt]=head[x];data[cnt]=y;wei[cnt]=b;flow[cnt]=a;head[x]=cnt++;
from[cnt]=y;nxt[cnt]=head[y];data[cnt]=x;wei[cnt]=-b;flow[cnt]=0;head[y]=cnt++;
}
bool BFS(){
memset(dis,0x3f,sizeof dis);
q.push(ss);dis[ss]=0;in_stack[ss]=true;
pre[ss]=pre[tt]=-1;
while(!q.empty()){
int now=q.front();
q.pop();
in_stack[now]=false;
for(int i=head[now];i!=-1;i=nxt[i]){
if(flow[i]&&wei[i]+dis[now]<dis[data[i]]){
dis[data[i]]=wei[i]+dis[now];
pre[data[i]]=(i^1);
if(!in_stack[data[i]]){q.push(data[i]);in_stack[data[i]]=true;}
}
}
}
return pre[tt]>0;
}
void dfs(){
int Low=INF;
for(int i=pre[tt];i!=-1;i=pre[data[i]])Low=Min(Low,flow[i^1]);
for(int i=pre[tt];i!=-1;i=pre[data[i]]){
flow[i^1]-=Low;
flow[i]+=Low;
}
}
int main(){
memset(head,-1,sizeof head);
scanf(”%d%d%d%d%d%d”,&N,&p,&m,&f,&n,&s);
for(int i=1;i<=N;i++){
int x;
scanf(”%d”,&x);
add(i+N,tt,x,0);
add(ss,i,x,0);
if(i+m<=N)add(i,i+N+m,INF,f);
if(i+n<=N)add(i,i+N+n,INF,s);
if(i!=N)add(i,i+1,INF,0);
add(ss,i+N,INF,p);
}
while(BFS())dfs();
for(int i=0;i<cnt;i++){
if(from[i]>=1&&from[i]<=N&&data[i]>=N+1&&data[i]!=tt&&data[i]!=ss)ans+=flow[i^1]*wei[i];
if(from[i]==ss&&data[i]>=N+1&&data[i]!=tt&&data[i]!=ss)ans+=flow[i^1]*wei[i];
}
printf(”%d\n”,ans);
return 0;
}
相关文章推荐
- Android网络编程基础简介
- iOS 网络编程:XML解析
- 基于语义网络进行图像标注 Image Annotation on the Semantic Web
- http接口自动化测试框架实现
- UNIX网络编程:IPC之消息队列
- 从JAVA多线程理解到集群分布式和网络设计的浅析
- AsyncHttpClient+mysql 中文乱码问题
- APP开发实战25-HTTP运作方式
- APP开发实战24-HTTP协议简介
- C#网络编程 (三) 多线程概述
- 为 MySQL 增加 HTTP/REST 客户端:MySQL UDF 函数 mysql-udf-http 1.0 发布
- HTTP头部信息解释分析(详细整理)
- HNOI2016 Day2 T2 网络<树链剖分>
- 为 MySQL 增加 HTTP/REST 客户端:MySQL UDF 函数 mysql-udf-http 1.0 发布
- 一个有效的与第三方进行网络通信实践
- Mac OS X 跟新到10.11后cocoapods安装出现的问题(- bad response Not Found 404 (http://ruby.taobao.org/latest_spe)
- 常见的http错误代码
- OSI七层网络模型与TCP/IP四层网络模型
- C#网络编程 (二) 数据流的类型和应用
- 网络攻防平台第七关