餐巾计划问题 【网络流24题】【费用流】【zkw】

题目描述

一个餐厅在相继的 NN 天里,每天需用的餐巾数不尽相同。假设第 ii 天需要 r_iri?块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 pp 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 nn 天(n>mn>m),其费用为 ss 分(s<fs<f)。

每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。

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

输入格式

由标准输入提供输入数据。文件第 1 行有 1 个正整数 NN,代表要安排餐巾使用计划的天数。

接下来的一行是餐厅在相继的 NN 天里,每天需用的餐巾数。

最后一行包含5个正整数p,m,f,n,sp,m,f,n,s。pp 是每块新餐巾的费用; mm 是快洗部洗一块餐巾需用天数; ff 是快洗部洗一块餐巾需要的费用; nn 是慢洗部洗一块餐巾需用天数; ss 是慢洗部洗一块餐巾需要的费用。

输出格式

将餐厅在相继的 N 天里使用餐巾的最小总花费输出

输入输出样例

输入 #1复制

3
1 7 5
11 2 2 3 1

输出 #1复制

134

说明/提示

N<=2000

ri<=10000000

p,f,s<=10000

时限4s

思路

  如何建图:

       首先,因为有两类状态——干净和脏毛巾,考虑把日期拆成毛巾的使用量和需求量。

       如果用最朴素的建图方法:

                                      

       会发现,每天的脏毛巾是可以存起来等到下一次一起洗,就会导致一个问题,容量 a [ i ]  的限制会导致最后取到的不是所有毛巾的总花费。

       如何让每条毛巾的花费都被算上,就要考虑怎样跑满最大流的问题。

       显然我们可以针对上图的缺点来重新考虑建图:

            

       如此一来,就满足了基本的条件:脏毛巾留到下一天的脏毛巾,脏毛巾送去洗,购置新毛巾,同时由于两种量之间的关系不再是线性转移,保证了能跑满最大流。

       然后上 zkw 跑 MCMF即可。

CODE

 

#include <bits/stdc++.h>

using namespace std;

#define int long long

template<class T>inline void read(T &res)

{

char c;T flag=1;

while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;res=c-‘0‘;

while((c=getchar())>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘;res*=flag;

}

const int MAXN = 2e3 + 5;

const int inf = 0x3f3f3f3f;

int N;

struct Edge{

int to, val, cost;

Edge *next, *ops;

Edge(int to, int val, int cost, Edge *next): to(to), val(val), cost(cost), next(next){}

};

Edge *head[MAXN << 1];

void BuildGraph(int u, int v, int w, int c) {

head[u] = new Edge(v, w, c, head[u]);

head[v] = new Edge(u, 0, -c, head[v]);

head[u]->ops = head[v]; head[v]->ops = head[u];

}

namespace zkw{

int s, t, ans, res;

int dis[MAXN << 1];

bool vis[MAXN << 1];

bool Spfa() {

memset(vis, false, sizeof vis);

memset(dis, 0x3f, sizeof dis);

deque<int> q;

q.push_back(s);

vis[s] = true; dis[s] = 0;

while (!q.empty()) {

int u = q.front(); q.pop_front(); vis[u] = false;

for (Edge *e = head[u]; e; e = e->next) {

int v = e->to;

if (e->val > 0 && dis[u] + e->cost < dis[v]) {

dis[v] = dis[u] + e->cost;

if (!vis[v]) {

vis[v] = true;

if (!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);

else q.push_back(v);

}

}

}

}

return dis[t] < inf;

}

int Dfs(int u, int flow) {

if (u == t) {

vis[u] = true;

res += flow;

return flow;

}

int used = 0; vis[u] = true;

for (Edge *e = head[u]; e; e = e->next) {//当前弧就不加了

int v = e->to;

if ((!vis[v] || v == t) && e->val && dis[u] + e->cost == dis[v]) {

int mi = Dfs(v, min(e->val, flow - used));

if (mi) {

e->val -= mi;

e->ops->val += mi;

ans += e->cost * mi;

used += mi;

}

if (used == flow) break;

}

}

return used;

}

void Work() {

res = 0; ans = 0;

while (Spfa()) {

vis[t] = true;

while (vis[t]) {

memset(vis, false, sizeof vis);

Dfs(s, inf);

}

}

}

}

signed main() {

read(N);

zkw :: s = 0; zkw :: t = N * 2 + 1;

int s = 0, t = 2 * N + 1;

for ( int i = 1; i <= N; ++i ) {

int x; read(x);

BuildGraph(s, i, x, 0);

BuildGraph(i + N, t, x, 0);

}

int p, m, f, n, S;

read(p); read(m); read(f); read(n); read(S);

for ( int i = 1; i <= N; ++i ) {

BuildGraph(s, i + N, inf, p);

if(i + m <= N)

BuildGraph(i, i + N + m, inf, f);

if(i + n <= N)

BuildGraph(i, i + N + n, inf, S);

if(i + 1 <= N)

BuildGraph(i, i + 1, inf, 0);

}

zkw :: Work();

cout << zkw :: ans << endl;

return 0;

}

原文地址:https://www.cnblogs.com/orangeko/p/12583177.html

时间: 2024-10-11 03:09:38

餐巾计划问题 【网络流24题】【费用流】【zkw】的相关文章

【luogu1251】餐巾计划问题--网络流建模,费用流

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

太空飞行计划问题(网络流24题)

题意 有m个实验,n个器材,每个实验做完会得到一些钱,每个实验需要一些器械才能完成,买器材会花钱,器材可以一起用,求最大利益. n,m<=50 题解 直接写做法了,没做过就想不出来. 源点向实验连边,流量为实验所得的钱,器材想汇点连边,流量为器材花费,实验与相应的器材连边,流量inf. 先假设没花钱做了所有实验得到了所有钱ans(不要face). 求一遍最小割即可,ans-最小割就是答案. 割掉实验的连边就是不做这个实验,割掉器材的连边就是买这个器材. 输出方案就输出与s连通的即可.(为啥我也不

【网络流24题】餐巾计划问题(最小费用最大流)

[网络流24题]餐巾计划问题(最小费用最大流) 题面 COGS 洛谷上的数据范围更大,而且要开longlong 题解 餐巾的来源分为两种: ①新买的 ②旧的拿去洗 所以,两种情况分别建图 先考虑第一种 因为新买餐巾没有任何限制,并且随时可以买 所以直接从源点向每一天连边,容量为INF,费用为餐巾的价格 因为流要流出去,所以每个点向汇点连边,容量为每天的用量,费用为0 第二种,旧的拿去洗 首先考虑一下怎么算有多少旧的餐巾 每天用旧的餐巾的数量值一定的,不可能变多 因此从源点向这些点连边,容量为每天

网络流(费用流):[网络流24题] 餐巾

[网络流24题] 餐巾 [问题描述] 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p).如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此. (3)把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f). 在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部.在每天开始时,餐厅必须决定是否购买新餐

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

【网络流24题】餐巾计划(图解)

LOJ 6008[网络流24题]餐巾计划 题解 一张图片说明建图方法: 解说: 这种建图方法完美区分开了"脏餐巾"和"干净餐巾"两种餐巾. 每天一定会有r[i]个脏餐巾,所以源点向每天的"脏餐巾"(图上used)连边,容量r[i],费用是0.另外,前一天的脏餐巾也可以留到下一天再处理,所以每天的used点向下一天的used点连一条边,容量INF,费用是0. 每天会需要r[i]个干净餐巾,所以每天的"干净餐巾"向汇点连边(图上n

LOJ #6008. 「网络流 24 题」餐巾计划

#6008. 「网络流 24 题」餐巾计划 题目描述 一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同.假设第 i ii 天需要 ri r_ir?i?? 块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分:或者把旧餐巾送到快洗部,洗一块需 M MM天,其费用为 F FF 分:或者送到慢洗部,洗一块需 N NN 天,其费用为 S SS 分(S<F S < FS<F). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.

【费用流】【网络流24题】【cogs 739】运输问题

739. [网络流24题] 运输问题 ★★ 输入文件:tran.in 输出文件:tran.out 简单对比 时间限制:1 s 内存限制:128 MB ?问题描述: ?编程任务: 对于给定的m 个仓库和n 个零售商店间运送货物的费用,计算最优运输方案和最差运输方案. ?数据输入: ?结果输出: 程序运行结束时,将计算出的最少运输费用和最多运输费用输出到文件tran.out中. 输入文件示例 输出文件示例 tran.in 2 3 220 280 170 120 210 77 39 105 150 1

[网络流24题] 太空飞行计划 (最大权闭合子图---网络最大流)

727. [网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={ I1, I2,…,In }.实验Ej 需要用到的仪器是I的子集Rj∈I.配置仪器Ik 的费用为ck 美元.实验Ej

【网络流24题】航空线路问题(费用流)

[网络流24题]航空线路问题(费用流) 题面 Cogs数据有误,提供洛谷题面 题解 这题和原来做过的一道题周游加拿大是一模一样的 所以,这题DP+记录方案应该也是可行的 来考虑网络流的做法 现在的来回,被看成是去两次 所以流量被限定死了,为2 因此要考虑费用流来求解. 每个点只能经过一次 很显然先拆点 如果一个城市被访问了 那么,他的两个点直接的流量是一定存在的 为了记录下这个点被访问过 所以,给定它一个费用1 然后其他的连边和原来做的题目没有什么区别 对于每一条航线,从\(i'\)向\(j\)