把每天拆成两个点,需要用的餐巾数和用了的餐巾数,分别连源和汇,流量day[i],费用0
再从源点每天用的餐巾点,费用为p,流量无穷。
每天需要用的餐巾连下一天需要用的(没洗的),流量无穷,费用0;
每天用完的连n和m天后的用了的餐巾,费用f,s,流量无穷
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int inf = 100000000; const static int V = 2010; const static int E = 400000; int sink, source, dis[V], pre[V]; bool vst[V]; int day[V]; struct Edge { int v, flow, cost; Edge *next; }pool[E], *adj[V],*pree[V],*pp; void create(int u, int v, int flow, int cost) { pp->flow = flow; pp->v = v; pp->cost = cost; pp->next = adj[u]; adj[u] = pp++; } void addedge(int u, int v, int flow, int cost) { //printf("%d %d %d %d\n",u,v,flow,cost); create(u,v,flow,cost); create(v,u,0,-cost); } void SPFA() { int u; for (int i = 0; i < V; ++i) dis[i] = inf; memset(vst,0,sizeof(vst)); queue<int> q; q.push(source); vst[source] = 1; dis[source] = 0; while(!q.empty()) { int v = q.front(); q.pop(); for (Edge *i = adj[v]; i != NULL; i = i->next) { if (!i->flow) continue; u = i->v; if (i->cost + dis[v] < dis[u]) { dis[u] = i->cost + dis[v]; pree[u] = i; pre[u] = v; if (!vst[u]) { q.push(u); vst[u] = true; } } } vst[v] = false; } } void init() { memset(adj, 0, sizeof (adj)); pp = pool; } int Mincost_Maxflow() { int flow = 0, cost = 0; while (true) { SPFA(); if (dis[sink] == inf) break; int minn = inf; for (int i = sink; i != source; i = pre[i]) minn = min(minn, pree[i]->flow); flow += minn; for (int i = sink; i != source; i = pre[i]) { pree[i]->flow -= minn; pool[(pree[i] - pool)^0x1].flow += minn; cost += minn * pree[i]->cost; } } return cost; } int main() { int N,p,m,f,n,s; while(scanf("%d %d %d %d %d %d",&N,&p,&m,&f,&n,&s) == 6) { init(); source = 0; sink = 2*N + 1; for(int i=1;i<=N;i++) { scanf("%d",&day[i]); addedge(source,2*i-1,day[i],0); addedge(source,2*i,inf,p); addedge(2*i,sink,day[i],0); if(i + 1 <= N) addedge(2*i - 1,2*(i+1) - 1,inf,0); if(i + m <=N) addedge(2*i - 1,2*(i + m),inf,f); if(i + n <=N) addedge(2*i - 1,2*(i + n),inf,s); } int ff = Mincost_Maxflow(); printf("%d\n",ff); } return 0; }