很简单的费用流。。。。拆点就行
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 405; const int maxm = 400005; const int INF = 0x3f3f3f3f; struct Edge { int v, c, w, next; Edge () {} Edge(int v, int c, int w, int next) : v(v), c(c), w(w), next(next) {} }E[maxm]; set<int> ss[maxn]; queue<int> q; int H[maxn], cntE; int visit[maxn]; int cap[maxn]; int vis[maxn]; int dis[maxn]; int cur[maxn]; int flow, cost, s, t, T; void addedges(int u, int v, int c, int w) { E[cntE] = Edge(v, c, w, H[u]); H[u] = cntE++; E[cntE] = Edge(u, 0, -w, H[v]); H[v] = cntE++; } bool spfa() { memset(dis, INF, sizeof dis); cur[s] = -1; vis[s] = ++T; cap[s] = INF; dis[s] = 0; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = T - 1; for(int e = H[u]; ~e; e = E[e].next) { int v = E[e].v, c = E[e].c, w = E[e].w; if(c && dis[v] > dis[u] + w) { dis[v] = dis[u] + w; cap[v] = min(cap[u], c); cur[v] = e; if(vis[v] != T) { vis[v] = T; q.push(v); } } } } if(dis[t] == INF) return false; cost += cap[t] * dis[t]; flow += cap[t]; for(int e = cur[t]; ~e; e = cur[E[e ^ 1].v]) { E[e].c -= cap[t]; E[e ^ 1].c += cap[t]; } return true; } int mfmc() { flow = cost = 0; while(spfa()); return cost; } void init() { cntE = T = 0; memset(H, -1, sizeof H); memset(vis, 0, sizeof vis); } int a[maxn]; void work(int N) { int p, n, m, ss, f; s = 0, t = 2 * N + 1; for(int i = 1; i <= N; i++) scanf("%d", &a[i]); scanf("%d%d%d%d%d", &p, &m, &f, &n, &ss); for(int i = 1; i <= N; i++) { addedges(s, i, a[i], 0); addedges(s, i + N, a[i], p); addedges(i + N, t, a[i], 0); } for(int i = 1; i <= N; i++) { for(int j = i + m; j <= N; j++) addedges(i, j + N, a[i], f); for(int j = i + n; j <= N; j++) addedges(i, j + N, a[i], ss); } printf("%d\n", mfmc()); } int main() { freopen("napkin.in", "r", stdin); freopen("napkin.out", "w", stdout); int N; while(scanf("%d", &N) != EOF) { init(); work(N); } return 0; }