餐巾计划问题

题目描述

一个餐厅在相继的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 天里使用餐巾的最小总花费。

样例输入

3 10 2 3 3 2
5
6
7

样例输出

145
http://218.5.5.242:9018/JudgeOnline/problem.php?cid=1070&pid=1
从源点向每个i连边费用f,流量INF的边。
源点向每个i’连费用0,流量为当天流量的边。
从每个i向汇点连流量当天数量,费用0的边。
从每个i’向i+1’连费用为0,流量INF的边。
从每个i’分别向i-a连流量为INF,费用为fa的边(i’>a)
从每个i’分别向i-b连流量为INF,费用为fb的边(i>b)
然后跑模板 e。。
我顺便挖个坑,做完网络流24题
虽然路漫漫其修远兮。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define S 0
#define T 2001
#define MAXN 100005
#define INF 200000000
using namespace std;
inline int read()
{
    int  x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int q[100001],top,tail;
int ans=0;
bool mark[MAXN];
int n,m,cnt=1,head[MAXN],d[MAXN],from[MAXN],f,fa,fb,a,b;
struct tu{
    int from,w,to,next,c;
}bian[100001];
void ins(int f,int t,int w,int c)
{
    bian[++cnt].next=head[f];
    head[f]=cnt;
    bian[cnt].to=t;
    bian[cnt].w=w;
    bian[cnt].c=c;
    bian[cnt].from=f;
}
void insw(int f,int t,int w,int c)
{ins(f,t,w,c);ins(t,f,0,-c);}
bool spfa()
{
    for(int i=1;i<=T;i++)d[i]=INF;
    top=tail=10005;q[top]=S;mark[S]=1;d[S]=0;
    while(top>=tail)
    {
        int u=q[tail++];
        for(int i=head[u];i;i=bian[i].next)
        if(bian[i].w&&d[u]+bian[i].c<d[bian[i].to])
        {
            d[bian[i].to]=d[u]+bian[i].c;from[bian[i].to]=i;
            if(!mark[bian[i].to])
            {
                if(d[bian[i].to]<d[q[tail]]) q[--tail]=bian[i].to;
                else q[++top]=bian[i].to; mark[bian[i].to]=1;
            }        
        }    
        mark[u]=0;
    }
    return d[T]!=INF;
}
void mcf()
{
    int minn=INF;
    for(int i=from[T];i;i=from[bian[i].from])
        minn=min(minn,bian[i].w);
    for(int i=from[T];i;i=from[bian[i].from])
    {
        ans+=bian[i].c*minn;
        bian[i].w-=minn;
        bian[i^1].w+=minn;    
    }
}
int main()
{
     n=read();f=read();b=read();fb=read();a=read();fa=read();
     for(int i=1;i<=n;i++)
    {   
        insw(S,i,INF,f);
        int x=read();
        insw(S,i+n,x,0);
        insw(i,T,x,0);
        if(i-a>0)insw(i+n-a,i,INF,fa);
        if(i-b>0)insw(i+n-b,i,INF,fb);
    }
    for(int i=1;i<n;i++)insw(i+n,i+n+1,INF,0);
       while(spfa())mcf();
    printf("%d",ans);
    return 0;
}



posted @ 2017-03-26 12:50  0degreeofsail  阅读(164)  评论(0编辑  收藏  举报