餐巾计划问题
题目描述
一个餐厅在相继的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;
}