某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。
第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000)
第2行:U1 , U2 , … , Ui , … , Un (0<=Ui<=10000)
第3行:d1 , d2 , …, di , … , dn (0<=di<=100)
只有1行,一个整数,代表最低成本
3 1 1000
2 4 8
1 2 4
34
最小费用最大网络流
下面讲一下建图:
建一个源点,与每一个月连接上,费用是物品单价,容量无限大,因为可以买无限个物品
然后每个月之间可以继承物品,费用就是贮存费用,容量是仓库容量
最后建一个汇点,与每一个月的连接起来,费用是0(卖出不需要成本), 容量是每月需求量
然后配上最小费用最大流模板就A了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int inf = 1e9;
int n, m, S, t, tt, ans, s;
int u[10005], d[10005], c[10005], h[10005], dis[10005], prev[10005];
struct node
{
int from, to, flow, val, num, next;
}g[100005];
void add(int x, int y, int flow, int val)
{
g[++tt] = (node) {x, y, flow, val, tt + 1, h[x]}; h[x] = tt;//正向边
g[++tt] = (node) {y, x, 0, -val, tt - 1, h[y]}; h[y] = tt; //反向边
}
bool spfa()
{
memset(c, 0, sizeof(c));
queue<int>Q;
for (int i = 0; i <= n + 1; ++i) dis[i] = inf;
dis[s] = 0;
c[s] = 1;
Q.push(s);
while (Q.size())
{
int x = Q.front();
Q.pop();
for (int i = h[x]; i; i = g[i].next)
{
if (g[i].flow && dis[g[i].to] > dis[x] + g[i].val)
{
dis[g[i].to] = dis[x] + g[i].val;
prev[g[i].to] = i;
if (!c[g[i].to]) {
Q.push(g[i].to);
c[g[i].to] = 1;
}
}
}
c[x] = 0;
}
if (dis[t] == inf) return 0;
else return 1;
}
void mcf()
{
int x;
int flow_ = inf; x = t;
while (prev[x])
{
flow_ = min(flow_, g[prev[x]].flow);
x = g[prev[x]].from;
}
ans += flow_ * dis[t];
x = t;
while (prev[x])
{
g[prev[x]].flow -= flow_;
g[g[prev[x]].num].flow += flow_;
x = g[prev[x]].from;
}
}
int main()
{
scanf("%d%d%d", &n, &m, &S);
for (int i = 1; i <= n; ++i)
scanf("%d", &u[i]);
for (int i = 1; i <= n; ++i)
scanf("%d", &d[i]);
s = 0; t = n + 1;
for (int i = 1; i <= n; ++i)
add(s, i, 1e9, d[i]);
for (int i = 1; i < n; ++i)
add(i, i + 1, S, m);
for (int i = 1; i <= n; ++i)
add(i, t, u[i], 0);
while(spfa()) mcf();
printf("%d", ans);
}