n个服务器,k类任务,每个服务器完成一个任务都有特定的花费$cost_{i,j}$,但是你设置好某台机器去完成某项任务时他只能去完成这类任务,除非你可以花费$C$去更改配置。第$i$天要求去完成$q_{i,j}$个j类任务,问如何让总代价最小
用费用流去优化dp
#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i)
#define dwn(i, j, k) for (int i = int(j); i >= int(k); -- i)
typedef long long LL;
typedef pair<int, int> P;
typedef vector<int> VI;
typedef vector<P> VII;
const int inf = 1e9;
const int N = 50;
int cost[20][20], a[110][20], dp[110];
struct Edge {
int from, to, cap, flow, cost;
};
struct MCMF {
int n;
vector<Edge> edges;
vector<int> g[N];
int inq[N], d[N], p[N], a[N];
void add(int u, int v, int cap, int cost) {
edges.push_back((Edge){u, v, cap, 0, cost});
edges.push_back((Edge){v, u, 0, 0, -cost});
int m = edges.size();
g[u].push_back(m - 2);
g[v].push_back(m - 1);
}
bool spfa(int s, int t, int &flow, int &cost){
rep(i, 0, n) d[i] = inf;
memset(inq, 0, sizeof(inq));
d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf;
queue<int> Q;
Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
for (int i = 0; i < g[u].size(); ++ i) {
Edge &e = edges[g[u][i]];
if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
p[e.to] = g[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to] = 1;
}
}
}
}
if (d[t] == inf) return 0;
flow += a[t];
cost += d[t] * a[t];
int u = t;
while (u != s) {
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t];
u = edges[p[u]].from;
}
return 1;
}
int minCost(int s, int t) {
int flow = 0, cost = 0;
while (spfa(s, t, flow, cost)) continue; return cost;
}
}solver;
int main() {
int n, k, c, m;
scanf("%d%d%d", &n, &k, &c); // n个服务器,k类任务
scanf("%d", &m);
memset(cost, -1, sizeof(cost));
rep(i, 1, m) {
int s, t, w;
scanf("%d%d%d", &s, &t, &w);
cost[s][t] = w; // s 完成第t个任务的代价为w
}
int q;
scanf("%d", &q);
rep(i, 1, q) {
rep(j, 1, k) scanf("%d", &a[i][j]); // 第i天需要j服务器的数量
rep(j, 1, k) a[i][j] = a[i - 1][j] + a[i][j];
}
auto calcCost = [&](int l, int r) -> int{
static int sum[20];
rep(i, 1, k) sum[i] = a[r][i] - a[l - 1][i];
// rep(i, 1, k) cout << sum[i] << ' '; cout << '\n';
rep(i, 0, solver.n) solver.g[i].clear();
solver.edges.clear();
// n 个服务器, k 类任务
int src = n + k + 1, dest = n + k + 2;
solver.n = dest;
rep(i, 1, n) solver.add(src, i, 1, 0);
rep(i, 1, n) rep(j, 1, k)
if (cost[i][j] >= 0 && sum[j]) solver.add(i, j + n, 1, cost[i][j] * sum[j]);
// 必须要第i个服务器可以完成第j类任务
rep(i, 1, k) solver.add(i + n, dest, sum[i] > 0, 0);
return solver.minCost(src, dest);
};
dp[0] = 0;
rep(i, 1, q) {
dp[i] = inf;
rep(j, 0, i - 1) dp[i] = min(dp[i], dp[j] + calcCost(j + 1, i) + c);
}
printf("%d\n", dp[q]);
}
/*
5 5 10
12
1 1 63
2 1 37
2 2 12
3 2 98
5 2 57
2 3 74
3 3 55
4 3 32
1 4 62
3 4 18
2 5 21
4 5 42
10
97 20 29 95 46
51 32 96 53 37
60 85 50 23 94
92 11 53 26 46
66 64 18 0 58
18 2 3 97 37
17 11 73 7 93
36 30 31 27 51
22 35 31 77 1
83 68 66 64 64
*/
来源:https://www.cnblogs.com/tempestT/p/10764883.html