#bzoj2375#餐巾计划问题(费用流建图经典模型)

来源:互联网 发布:js获取input text的值 编辑:程序博客网 时间:2024/05/17 21:43

2375: 【网络流】餐巾计划问题

时间限制: 1 Sec  内存限制: 128 MB

题目描述

一个餐厅在相继的N 天里,每天需用的餐巾数不尽相同。假设第i天需要ri块餐巾(i=1,2,…,N)。餐厅可以购买新的餐巾,每块餐巾的费用为p分;或者把旧餐巾送到快洗部,洗一块需m天,其费用为f 分;或者送到慢洗部,洗一块需n 天(n>m),其费用为s<f 分。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好N 天中餐巾使用计划,使总的花费最小。

输入

文件第1 行有6 个正整数N,p,m,f,n,s。N 是要安排餐巾
使用计划的天数;p 是每块新餐巾的费用;m 是快洗部洗一块餐巾需用天数;f 是快洗部洗
一块餐巾需要的费用;n是慢洗部洗一块餐巾需用天数;s是慢洗部洗一块餐巾需要的费用。
接下来的N 行是餐厅在相继的N 天里,每天需用的餐巾数。

输出

程序运行结束时,将餐厅在相继的N 天里使用餐巾的最小总花费输出到文件output.txt中。

样例输入

3 10 2 3 3 2567

样例输出

145

建立一个二分图,X部Y部各N个点,

Xi表示第i天用掉的餐巾数,从Src连边至Xi边的容量为x(即题中给出的每天要用的数量),

Yi表示第i天之前至少要准备好的(即第i天需要用的)餐巾数,从Yi连边至Tar边的容量为x

对于Xi,

可以选择将Xi中的移至快洗部Xi -> Yi + m,容量无限,费用f,

可以移至慢洗部Xi -> Yi + n,容量无限,费用s,

还可以留下来到下一天Xi -> Xi + 1,容量无限,费用0

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<queue>using namespace std; const int Max = 2005;const int Maxm = 100005;const int INF = 0x3f3f3f3f; struct node{    int v, cap, cost, nxt;}edge[Maxm << 2]; int N, p, m, f, n, s;int cnt = 1, Src, Tar, Flow, Cost;int fir[Max], Dis[Max];bool vis[Max], Inq[Max]; void getint(int & num){    char c; int flg = 1;    num = 0;    while((c = getchar()) < '0' || c > '9')   if(c == '-')    flg = -1;    while(c >= '0' && c <= '9'){  num = num * 10 + c - 48;    c = getchar();}    num *= flg;} void addedge(int a, int b, int c, int d){    edge[++ cnt].v = b, edge[cnt].cap = c, edge[cnt].cost = d, edge[cnt].nxt = fir[a], fir[a] = cnt;    edge[++ cnt].v = a, edge[cnt].cap = 0, edge[cnt].cost = -d, edge[cnt].nxt = fir[b], fir[b] = cnt;} int Aug(int i, int augco){    if(i == Tar){        Cost += Dis[Tar] * augco;        return augco;    }    int augc = augco, delta;    for(int j = fir[i]; j && augc; j = edge[j].nxt) if(edge[j].cap && ! vis[edge[j].v])        if(Dis[i] == Dis[edge[j].v] - edge[j].cost){            vis[edge[j].v] = 1;            delta = Aug(edge[j].v, min(augc, edge[j].cap));            edge[j].cap -= delta;            edge[j ^ 1].cap += delta;            augc -= delta;        }    return augco - augc;} queue<int>Q;bool SPFA(){    memset(Dis, 0x3f, sizeof(Dis));    memset(Inq, 0, sizeof(Inq));    Dis[Src] = 0;    Q.push(Src);    while(! Q.empty()){        int tmp = Q.front();    Q.pop();        Inq[tmp] = 0;        for(int j = fir[tmp]; j; j = edge[j].nxt)            if(edge[j].cap && Dis[edge[j].v] > Dis[tmp] + edge[j].cost){                Dis[edge[j].v] = Dis[tmp] + edge[j].cost;                if(! Inq[edge[j].v])    Inq[edge[j].v] = 1, Q.push(edge[j].v);            }    }    return Dis[Tar] != Dis[Tar + 1];} int MCMF(){Flow = 0, Cost = 0;while(SPFA()){memset(vis, 0, sizeof(vis));vis[Src] = 1;Flow += Aug(Src, INF);}return Cost;}int  main(){    getint(N), getint(p), getint(m), getint(f), getint(n), getint(s);Src = 0, Tar = N << 1| 1;int x;for(int i = 1; i <= N; ++ i){getint(x);addedge(Src, i, x, 0);addedge(i + N, Tar, x, 0);addedge(Src, i + N, INF, p);if(i + m <= N)addedge(i, i + m + N, INF, f);if(i + n <= N)addedge(i, i + n + N, INF, s);if(i < N)addedge(i, i + 1, INF, 0);}printf("%d\n", MCMF());    return 0;}









阅读全文
0 0
原创粉丝点击