P1251 餐巾计划问题
题目描述
一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同。假设第 iii 天需要 rir_iri块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s 分(s<f)。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。
输入输出格式
输入格式:
由标准输入提供输入数据。文件第 1 行有 1 个正整数 NNN,代表要安排餐巾使用计划的天数。
接下来的 NNN 行是餐厅在相继的 NNN 天里,每天需用的餐巾数。
最后一行包含5个正整数p,m,f,n,s。p 是每块新餐巾的费用; m 是快洗部洗一块餐巾需用天数; f是快洗部洗一块餐巾需要的费用; n是慢洗部洗一块餐巾需用天数; s是慢洗部洗一块餐巾需要的费用。
输出格式:
将餐厅在相继的 N 天里使用餐巾的最小总花费输出
输入输出样例
说明
N<=2000
ri<=10000000
p,f,s<=10000
时限4s
看到4S,顿时随便打代码,基本上啥优化都没有,就是莫名其妙被卡了好久,
和题解一样(我用多数组,题解是结构体),然后WA了好多……
最后一改成结构体就AC了,我也是很懵。
很显然,就是最大流的最小费用,
把每天拆成两个点,看成上下午。
上午负责洗毛巾,下午负责送毛巾……
AC代码如下:
#include <algorithm> #include <cstring> #include <cstdio> #include <queue> using namespace std; typedef long long LL; ,M=; const int INF=0x3f3f3f3f; LL n,p,m1,m2,f1,f2,head[N],cnt=,dis[N],last[N],r[N],s,t; bool inq[N]; struct Edge { LL u,v,cap,cost,nxt; } e[M]; void add(LL u,LL v,LL cap,LL cost) { e[cnt].u=u; e[cnt].v=v; e[cnt].cap=cap; e[cnt].cost=cost; e[cnt].nxt=head[u]; head[u]=cnt++; e[cnt].u=v; e[cnt].v=u; e[cnt].cap=; e[cnt].cost=-cost; e[cnt].nxt=head[v]; head[v]=cnt++; } bool SPFA() { memset(inq,,sizeof(inq)); memset(last,-,sizeof(last)); memset(dis,0x3f3f3f3f,sizeof(dis)); queue<LL> Q; Q.push(s); inq[s]=; dis[s]=; while (!Q.empty()) { LL u=Q.front(); Q.pop(); inq[u]=; ;i=e[i].nxt) { LL v=e[i].v; if (e[i].cap&&dis[v]>dis[u]+e[i].cost) { dis[v]=dis[u]+e[i].cost; last[v]=i; if (!inq[v]) { Q.push(v); inq[v]=; } } } } ; } LL MCMF() { LL minflow,mincost=; while (SPFA()) { minflow=INF+; ;i=last[e[i].u]) if (e[i].cap<minflow) minflow=e[i].cap; ;i=last[e[i].u]) { e[i].cap-=minflow; e[i^].cap+=minflow; } mincost+=dis[t]*minflow; } return mincost; } int main() { memset(head,-,sizeof(head)); scanf("%lld",&n); ;i<=n;i++) scanf("%lld",&r[i]); scanf("%lld%lld%lld%lld%lld",&p,&m1,&f1,&m2,&f2); s=,t=*n+; ;i<=n;i++) { add(s,i,r[i],); add(i+n,t,r[i],); add(s,i+n,INF,p); <=n) add(i,i+,INF,); if (i+m1<=n) add(i,i+n+m1,INF,f1); if (i+m2<=n) add(i,i+n+m2,INF,f2); } printf("%lld",MCMF()); ; }