1221: [HNOI2001] 软件开发
Time Limit: 10 Sec
Memory Limit: 162 MB
Submit: 1352
Solved: 749
[Submit][Status][Discuss]
题解:
经典网络流24题中的餐巾计划问题:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1e9;
const int N=2005;
const int M=100005;
int from[M],to[M],nxt[M],w[M],p[M],lj[N],cnt=1;
void add(int f,int t,int ww,int pp)
{
cnt++,from[cnt]=f,to[cnt]=t,nxt[cnt]=lj[f],lj[f]=cnt,w[cnt]=ww,p[cnt]=pp;
cnt++,from[cnt]=t,to[cnt]=f,nxt[cnt]=lj[t],lj[t]=cnt,w[cnt]=0,p[cnt]=-pp;
}
int day,fp,ff,fs,f,s,ans,S,T;
queue<int>Q;
int d[N],bef[N];
bool inq[N];
bool spfa()
{
for(int i=S;i<=T;i++) d[i]=inf;
d[S]=0;
Q.push(S);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
inq[x]=false;
for(int i=lj[x];i;i=nxt[i])
if(w[i]&&d[to[i]]>d[x]+p[i])
{
d[to[i]]=d[x]+p[i];
bef[to[i]]=i;
if(!inq[to[i]])
{
Q.push(to[i]);
inq[to[i]]=true;
}
}
}
if(d[T]==inf) return false;
return true;
}
void fyl()
{
while(spfa())
{
int x=T,flow=inf;
while(x!=S)
{
flow=min(flow,w[bef[x]]);
x=from[bef[x]];
}
x=T;
ans+=d[T]*flow;
while(x!=S)
{
w[bef[x]]-=flow;
w[(bef[x]^1)]+=flow;
x=from[bef[x]];
}
}
}
int main()
{
scanf("%d%d%d%d%d%d",&day,&f,&s,&fp,&ff,&fs);
S=0,T=day*2+1;
for(int i=1;i<=day;i++)
{
if(i+1<=day) add(i,i+1,inf,0);
if(i+f+1<=day) add(i,day+i+f+1,inf,ff);
if(i+s+1<=day) add(i,day+i+s+1,inf,fs);
add(S,day+i,inf,fp);
}
for(int i=1;i<=day;i++)
{
int x;
scanf("%d",&x);
add(S,i,x,0);
add(day+i,T,x,0);
}
while(spfa()) fyl();
printf("%d",ans);
}
Description
某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。
Input
第1行为n,a,b,f,fA,fB. 第2行为n1,n2,……,nn. (注:1≤f,fA,fB≤60,1≤n≤1000)
Output
最少费用
Sample Input
4 1 2 3 2 1
8 2 1 6
8 2 1 6
Sample Output
38
HINT
Source
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1e9;
const int N=2005;
const int M=100005;
int from[M],to[M],nxt[M],w[M],p[M],lj[N],cnt=1;
void add(int f,int t,int ww,int pp)
{
cnt++,from[cnt]=f,to[cnt]=t,nxt[cnt]=lj[f],lj[f]=cnt,w[cnt]=ww,p[cnt]=pp;
cnt++,from[cnt]=t,to[cnt]=f,nxt[cnt]=lj[t],lj[t]=cnt,w[cnt]=0,p[cnt]=-pp;
}
int day,fp,ff,fs,f,s,ans,S,T;
queue<int>Q;
int d[N],bef[N];
bool inq[N];
bool spfa()
{
for(int i=S;i<=T;i++) d[i]=inf;
d[S]=0;
Q.push(S);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
inq[x]=false;
for(int i=lj[x];i;i=nxt[i])
if(w[i]&&d[to[i]]>d[x]+p[i])
{
d[to[i]]=d[x]+p[i];
bef[to[i]]=i;
if(!inq[to[i]])
{
Q.push(to[i]);
inq[to[i]]=true;
}
}
}
if(d[T]==inf) return false;
return true;
}
void fyl()
{
while(spfa())
{
int x=T,flow=inf;
while(x!=S)
{
flow=min(flow,w[bef[x]]);
x=from[bef[x]];
}
x=T;
ans+=d[T]*flow;
while(x!=S)
{
w[bef[x]]-=flow;
w[(bef[x]^1)]+=flow;
x=from[bef[x]];
}
}
}
int main()
{
scanf("%d%d%d%d%d%d",&day,&f,&s,&fp,&ff,&fs);
S=0,T=day*2+1;
for(int i=1;i<=day;i++)
{
if(i+1<=day) add(i,i+1,inf,0);
if(i+f+1<=day) add(i,day+i+f+1,inf,ff);
if(i+s+1<=day) add(i,day+i+s+1,inf,fs);
add(S,day+i,inf,fp);
}
for(int i=1;i<=day;i++)
{
int x;
scanf("%d",&x);
add(S,i,x,0);
add(day+i,T,x,0);
}
while(spfa()) fyl();
printf("%d",ans);
}
本文介绍了一道经典的网络流题目——餐巾计划问题。该问题涉及如何通过最小花费来满足连续多天的餐巾需求,包括购买新餐巾、快速及慢速消毒等策略。文章详细解释了建模过程,并提供了完整的代码实现。

804

被折叠的 条评论
为什么被折叠?



