1221: [HNOI2001] 软件开发
Time Limit: 10 Sec
Memory Limit: 162 MB
Submit: 1166
Solved: 642
[ Submit][ Status][ Discuss]
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
Sample Output
38
HINT
Source
题解:与网络流24题的餐巾计划问题几乎一样,但是需要注意消毒毛巾需要A天,那么真正用上是在a+1天
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 100000
using namespace std;
int n,m,fa,fb,f,a,b,tot=-1,minn,flow;
int next[N],point[N],v[N],c[N],remain[N],d[N];
int dis[N],can[N],laste[N];
const int inf=1e9;
void add(int x,int y,int z,int k)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=k; remain[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=-k; remain[tot]=0;
}
int addflow(int s,int t)
{
int now=t; int ans=inf;
while (now!=s)
{
ans=min(ans,remain[laste[now]]);
now=v[laste[now]^1];
}
now=t;
while (now!=s)
{
remain[laste[now]]-=ans;
remain[laste[now]^1]+=ans;
now=v[laste[now]^1];
}
return ans;
}
bool spfa(int s,int t)
{
memset(dis,0x7f,sizeof(dis));
dis[s]=0; can[s]=1;
queue<int> p; p.push(s);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (dis[v[i]]>dis[now]+c[i]&&remain[i])
{
dis[v[i]]=dis[now]+c[i];
laste[v[i]]=i;
if (can[v[i]]==0)
{
can[v[i]]=1;
p.push(v[i]);
}
}
can[now]=0;
}
if (dis[t]>inf) return false;
int k=addflow(s,t);
flow+=k;
minn+=k*dis[t];
return true;
}
void maxflow(int s,int t)
{
while (spfa(s,t));
}
int main()
{
memset(next,-1,sizeof(next));
memset(point,-1,sizeof(point));
scanf("%d%d%d%d%d%d",&n,&a,&b,&f,&fa,&fb);
for (int i=1;i<=n;i++)
scanf("%d",&d[i]);
for (int i=1;i<=n;i++)
add(0,i,d[i],0),add(0,i+n,inf,f);
for (int i=1;i<=n;i++)
{
if (i+a+1<=n)
add(i,i+a+n+1,inf,fa);
if (i+b+1<=n)
add(i,i+b+n+1,inf,fb);
add(i+n,2*n+1,d[i],0);
if (i+1<=n) add(i,i+1,inf,0);
}
maxflow(0,2*n+1);
printf("%d\n",minn);
}