#2626 「网络流 24 题」餐巾计划
描述
/
一个餐厅在相继的 n 天里,每天需用的餐巾数不尽相同。假设第 i天需要 ri 块餐巾。餐厅可以购买新的餐巾,每块餐巾的费用为 P 分;或者把旧餐巾送到快洗部,洗一块需 M 天,其费用为 F 分;或者送到慢洗部,洗一块需 N 天,其费用为 S 分(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
提示
1≤n≤1000
/
思路:
其他的条件都不难操作,唯一一个麻烦的是 如何处理用完的拿给后面的(快洗和慢洗)
这里一种思路值得学习。 把每一天需要的,和用完后留下来的 用两个点分开表示
需要的: Ai 用完后剩下的: Bi
(有点像二分图)
Ai 和 T 连接 ,表示一天满足
S和 Ai连带 费用的 表示直接“买”
S 和 Bi 连 (每一天必应会产生废纸)
Bi 和 Ai+N ,Ai+M连接 表示快慢洗
小结:清晰直接的思路能减少很多不必要的讨论;
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e3+10,maxm=1e4+10;
const int INF=2e9;
struct edge{
int v,nxt,c,f;
}r[maxm];
int head[maxn],cnt=1;
inline void _add(int u,int v,int c,int f){
r[++cnt]=(edge){v,head[u],c,f};
head[u]=cnt;
}
int n,P,M,F,N,S,s,t;
int dis[maxn],vis[maxn];
bool spfa(int s,int t){
memset(vis,0,sizeof vis);
memset(dis,0x5f,sizeof dis);
dis[t]=0;vis[t]=1;
deque<int> q;
q.push_back(t);
while(!q.empty()){
int u=q.front();q.pop_front();vis[u]=0;
for(int i=head[u];i;i=r[i].nxt){
if(r[i^1].c&&dis[u]-r[i].f<dis[r[i].v]){
dis[r[i].v]=dis[u]-r[i].f;
if(!vis[r[i].v]){
vis[r[i].v]=1;
if(!q.empty()&&dis[r[i].v]<dis[q.front()])q.push_front(r[i].v);
else q.push_back(r[i].v);
}
}
}
}
return dis[s]<0x5f5f5f5f;
}
int ans=0;
int dfs(int u,int f){
if(u==t){
vis[t]=1;
return f;
}
int used=0,w;
vis[u]=1;
for(int i=head[u];i;i=r[i].nxt){
int v=r[i].v,c=r[i].c,ff=r[i].f;
if(!vis[v]&&c&&dis[u]-ff==dis[v]){
w=dfs(v,min(c,f-used));
//cerr<<u<<" "<<v<<" "<<w*ff<<endl;
ans+=w*ff,r[i].c-=w;
r[i^1].c+=w;used+=w;
if(used==f)break;
}
}
return used;
}
void get(){
while(spfa(s,t)){
vis[t]=1;
while(vis[t]){
memset(vis,0,sizeof vis);
dfs(s,INF);
}
}
}
int mov=1e3+10;
int a[maxn];
signed main(){
s=0,t=n+mov*2;
scanf("%d%d%d%d%d%d",&n,&P,&M,&F,&N,&S);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<=n;++i){
_add(s,i,a[i],0);_add(i,s,0,0);
_add(i,i+1,INF,0);_add(i+1,i,0,0);
_add(i,i+mov+M,INF,F);_add(i+mov+M,i,0,-F);
_add(i,i+mov+N,INF,S);_add(i+mov+N,i,0,-S);
_add(i+mov,t,a[i],0);_add(t,i+mov,0,0);
_add(s,i+mov,a[i],P);_add(i+mov,s,0,-P);
}
get();
printf("%d",ans);
return 0;
}