您的位置:首页 > 其它

[BZOJ]1221: [HNOI2001] 软件开发 费用流

2017-10-02 09:43 274 查看
Description

某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。

题解:

把每一天拆成两个点,其中一个表示今天需要用的毛巾,另一个表示今天剩下的毛巾,然后乱连边,注意今天可以有毛巾不用,留到以后用,因此WA了一次。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=1010;
const int inf=2147483647;
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<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
struct Edge{int x,y,d,c,next;}e[2110000];
int last[Maxn*2],len=1;
void ins(int x,int y,int d,int c)
{
int t=++len;
e[t].x=x;e[t].y=y;e[t].d=d;e[t].c=c;
e[t].next=last[x];last[x]=t;
}
void addedge(int x,int y,int d,int c){ins(x,y,d,c);ins(y,x,0,-c);}
int n,a,b,F,FA,FB,c[Maxn];
int st,ed;
in
4000
t f[Maxn*2],pre[Maxn*2];
bool in[Maxn*2];
queue<int>q;
bool spfa()
{
memset(f,63,sizeof(f));f[st]=0;
memset(in,false,sizeof(in));
q.push(st);pre[st]=-1;
while(!q.empty())
{
int x=q.front();q.pop();in[x]=false;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(e[i].d&&f[x]+e[i].c<f[y])
{
pre[y]=i;
f[y]=f[x]+e[i].c;
if(!in[y])in[y]=true,q.push(y);
}
}
}
return(f[ed]!=1061109567);
}
int ans=0;
void work()
{
int mind=inf,now=ed;
while(pre[now]!=-1)
{
mind=min(mind,e[pre[now]].d);
now=e[pre[now]].x;
}
now=ed;
while(pre[now]!=-1)
{
e[pre[now]].d-=mind;e[pre[now]^1].d+=mind;
ans+=mind*e[pre[now]].c;
now=e[pre[now]].x;
}
}
int main()
{
n=read();a=read();b=read();F=read();FA=read();FB=read();
for(int i=1;i<=n;i++)c[i]=read();
st=(n<<1);ed=st+1;
for(int i=1;i<=n;i++)
{
addedge(st,i,inf,F);//表示直接买毛巾
addedge(i,ed,c[i],0);//第i天必须有c[i]条毛巾
addedge(st,i+n,c[i],0);//第i天剩下c[i]条毛巾
if(i+a+1<=n)addedge(i+n,i+a+1,c[i],FA);//可以a消毒
if(i+b+1<=n)addedge(i+n,i+b+1,c[i],FB);//可以b消毒
if(i+1<=n)addedge(i,i+1,inf,0);//今天不用,留到下一天用
}
while(spfa())work();
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: