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