乙個餐廳在相繼的 nn 天裡,每天需用的餐巾數不盡相同。假設第 ii 天需要 r_iri塊餐巾( i=1,2,...,n)。餐廳可以購買新的餐巾,每塊餐巾的費用為 pp 分;或者把舊餐巾送到快洗部,洗一塊需 m 天,其費用為 f 分;或者送到慢洗部,洗一塊需 nn 天(n>mn>m),其費用為 ss 分(ss每天結束時,餐廳必須決定將多少塊髒的餐巾送到快洗部,多少塊餐巾送到慢洗部,以及多少塊儲存起來延期送洗。但是每天洗好的餐巾和購買的新餐巾數之和,要滿足當天的需求量。
試設計乙個演算法為餐廳合理地安排好 nn 天中餐巾使用計畫,使總的花費最小。程式設計找出乙個最佳餐巾使用計畫。
輸入格式:
由標準輸入提供輸入資料。檔案第 1 行有 1 個正整數 nn,代表要安排餐巾使用計畫的天數。
接下來的 nn 行是餐廳在相繼的 nn 天裡,每天需用的餐巾數。
最後一行包含5個正整數p,m,f,n,sp,m,f,n,s。pp 是每塊新餐巾的費用; mm 是快洗部洗一塊餐巾需用天數; ff 是快洗部洗一塊餐巾需要的費用; nn 是慢洗部洗一塊餐巾需用天數; ss 是慢洗部洗一塊餐巾需要的費用。
輸出格式:
將餐廳在相繼的 n 天裡使用餐巾的最小總花費輸出
輸入樣例#1: 複製
31 7 5
11 2 2 3 1
輸出樣例#1: 複製
134
n<=2000
ri<=10000000
p,f,s<=10000
時限4s
constint inf = 0x3f3f3f3f
;const
int maxn = 1000 + 10
;struct
edge
};vector
e;vector
g[maxn];
int a[maxn];//
找增廣路每個點的水流量
int p[maxn];//
每次找增廣路反向記錄路徑
int d[maxn];//
spfa演算法的最短路
int inq[maxn];//
spfa演算法是否在佇列中
intn, m;
void init(int
n)void addedge(int u, int v, int c, int
cost)
bool bellman(int s, int t, int& flow, long
long &cost)
//bellman 演算法入隊
} }
}if(d[t] == inf)return
false;//
找不到增廣路
flow += a[t];//
最大流的值,此函式引用flow這個值,最後可以直接求出flow
cost += (long
long)d[t] * (long
long)a[t];//
距離乘上到達匯點的流量就是費用
for(int u = t; u != s; u = e[p[u]].u)//
逆向存邊
return
true;}
int mincostmaxflow(int s, int t, long
long &cost)
這個題目建圖很難想,開始一點思路都沒有,看了看題解。
建圖:這個是把每一天拆成了兩個點,乙個上午點和乙個下午點。
下午點都和源點相連表示一天的結束,上午點和匯點相連,表示需要的餐巾數量。
與源點和匯點相連的點的cap都設定成這一天需要的餐巾數量,這個來限制送去快洗和慢洗的毛巾數。
然後再去處理3+1,3表示快洗,慢洗,新買,1表示不洗。因為之前以及被限制過了,
所以這裡的不需要再去考慮有多少髒毛巾,這裡的cap應該設定成inf,因為一次可以洗無數條毛巾。
這個不洗的要好好處理,這個不洗表示直接積累到下一天,那麼就說明,這個的cost=0,
但是我們會疑惑,如果這樣會不會影響到網路流? 其實這個不會,因為餐巾的積累會往下一天的晚上傳遞,意思
是說,這個餐巾不會算作這一天需要的餐巾數,但是那為什麼還要連邊呢?這個連邊會讓它往下一天傳遞,
那麼餐巾積累,之後可以考慮一起洗掉。一起洗一堆和一次洗一條所用的時間是一樣的,
所以如果我們之後再堆在一起洗也許會更優。
#include #include#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
using
namespace
std;
typedef
long
long
ll;const
int maxn =1e4;
struct
node
};vector
e;vector
g[maxn];
ints, t;
void add(int u, int v, int cap, int
cost)
intd[maxn], inq[maxn], a[maxn], p[maxn];
bool bellman(ll&cost)}}
}if (d[t] == inf) return
false
; cost += 1ll * d[t] * 1ll *a[t];
//printf("%lld\n", cost);
for(int i=t;i!=s;i=e[p[i]].from
)
return
true;}
void maxflow(ll &cost)
intmain()
intq, m, f, n, g;
cin >> q >> m >> f >> n >>g;
for (int i = 1; i <= n; i++)
if (i + m <=n)
if (i + n <=n)
add(s, n +i, inf, q);
}ll cost = 0
; maxflow(cost);
printf(
"%lld\n
", cost);
return0;
}
網路流之 最小費用最大流
學習最小費用最大流前,需要學習最大流演算法。在最大流演算法中,沒有考慮邊的費用問題。在mincostmaxflow中,引入了費用的概念 cij表示邊 i,j 單位流量的費用。在滿足流量 v f 的同時,並且要求費用最少。最小費用最大流的迭代演算法 1.求出從s到t的最小費用通路 spfa 和通路的最...
網路流 最小費用最大流
q 為什麼突然想搞網路流?a 迫於tham 蛤mu的淫威 用最短路演算法求出s t的路徑 把路徑要摳出來,而且每條邊要有容量 算一下路徑裡面的可以流過的最大的流量 發現此時的花費就是 dis t flow 累加即可.重複1 3直到不能夠到達t.include include include incl...
網路流之最小費用流
這是一道模板題。給定乙個圖,每條邊有容量和費用,使用每條邊的單位流量需要支付特定的費用。給定源點 1和匯點 n,求圖的最大流和最大流需要支付的最小費用。第一行兩個整數n,m,表示有 n 個點 m 條邊。從第二行開始的之後 m 行,每行四個整數s i t i c i w i 表示一條從 s i 到 t...