餐巾计划问题 网络流24题

题目描述

一个餐厅在相继的 NN 天里,每天需用的餐巾数不尽相同。假设第 ii 天需要 r_iri 块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 pp 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 nn 天( n>mn>m ),其费用为 ss 分( s<fs<f )。

每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。

试设计一个算法为餐厅合理地安排好 NN 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。

输入输出格式

输入格式:

由标准输入提供输入数据。文件第 1 行有 1 个正整数 NN ,代表要安排餐巾使用计划的天数。

接下来的 NN 行是餐厅在相继的 NN 天里,每天需用的餐巾数。

最后一行包含5个正整数 p,m,f,n,sp,m,f,n,s 。 pp 是每块新餐巾的费用; mm 是快洗部洗一块餐巾需用天数; ff 是快洗部洗一块餐巾需要的费用; nn 是慢洗部洗一块餐巾需用天数; ss 是慢洗部洗一块餐巾需要的费用。最小费用。

 
 
输出格式:

将餐厅在相继的 N 天里使用餐巾的最小总花费输出

思路:对于每天要用的餐巾,考虑它的来源,有可能是新购的,也有可能是快洗或慢洗后得到的,对于用过的餐巾,可以选择不作任何操作留到后一天,也可以快洗或者慢洗。 这样就可以把问题分成两部分考虑,剩下没处理的和每天需要的。对于第i天没处理的点ai,可以有源点得来,容量为每天需要的餐巾数,也可以由前一天得来,容量为无穷,对于每天需要的餐巾aj,可以有的源点得来,容量为需要的餐巾,费用为新购的费用,也可以由前m或n天快洗慢洗得来,费用为f,s。

点击打开链接

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const long long maxn=5000;
const long long maxm=1e6+5;
const long long inf=1000000000;
struct Edge{
    Edge() {};
    Edge(long long a,long long b,long long c,long long d) {
        v=a;
        f=b;
        w=c;
        nxt=d;
    }
    long long v,f,w,nxt;
};
long long n,p,fn,fp,sn,sp,lmt;
long long g[maxn+10];
Edge e[maxm*2+50];
long long nume;
long long src,sink;
void addedge(long long u,long long v,long long c,long long w) {

    e[++nume]=Edge(v,c,w,g[u]);
    g[u]=nume;
    e[++nume]=Edge(u,0,-w,g[v]);
    g[v]=nume;
}
queue<long long> que;
bool inQue[maxn+10];
long long dist[maxn+10];
long long Prev[maxn+10],pree[maxn+10];
bool findpath() {
    while(!que.empty()) {
        que.pop();
    }
    que.push(src);
    for(long long i=0;i<maxn+5;i++) dist[i]=inf;
    dist[src]=0;
    inQue[src]=true;
    while(!que.empty()) {
        long long u=que.front();
        que.pop();
        for(long long i=g[u];i;i=e[i].nxt) {
            if(e[i].f > 0 && dist[u] + e[i].w < dist[e[i].v]) {
                dist[e[i].v]=dist[u]+e[i].w;
                Prev[e[i].v]=u;
                pree[e[i].v]=i;
                if(!inQue[e[i].v]) {
                    inQue[e[i].v]=true;
                    que.push(e[i].v);
                }
            }
        }
        inQue[u]=false;
    }
    if(dist[sink]<inf) return true;
    else return false;
}
long long augment() {
    long long u=sink;
    long long delta=inf;
    while(u!=src) {
        if(e[pree[u]].f<delta) delta=e[pree[u]].f;
        u=Prev[u];
    }
    u=sink;
    while(u!=src) {
        e[pree[u]].f-=delta;
        e[pree[u]^1].f+=delta;
        u=Prev[u];
    }
    return dist[sink]*delta;
}
long long mincostflow() {
    long long cur=0;
    long long ans=0;
    while(findpath()) {
        cur+=augment();
        if(cur>ans)ans=cur;
    }
    return ans;
}
long long r[maxn];
int main() {
    while(scanf("%lld",&n) != EOF) {
        nume=1;
        memset(g,0,sizeof(g));
        for(long long i=1;i<=n;i++) {
            scanf("%lld",&r[i]);
        }
        scanf("%lld%lld%lld%lld%lld",&p,&fn,&fp,&sn,&sp);
        long long S=0,T=n+n+1;
        for(long long i=1;i<=n;i++) {
            addedge(S,i,r[i],0);
            addedge(i+n,T,r[i],0);
            addedge(S,i+n,inf,p);
            if(i+1<=n) addedge(i,i+1,inf,0);
            if(i+fn<=n) addedge(i,i+n+fn,inf,fp);
            if(i+sn<=n) addedge(i,i+n+sn,inf,sp);
        }
        src=S;
        sink=T;
        printf("%lld\n",mincostflow());
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41231363/article/details/80547750
今日推荐