文章目录
- 题目描述
- 解析
- 代码
题目描述
某软件公司正在规划一项nnn天的软件开发计划,根据开发计划第iii天需要nin_ini个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。
消毒方式有两种,A 种方式的消毒需要aaa天时间,B 种方式的消毒需要bbb天,A 种消毒方式的费用为每块毛巾faf_afa,B 种消毒方式的费用为每块毛巾fbf_bfb,而买一块新毛巾的费用为fff(新毛巾是已消毒的,当天可以使用)。公司经理正在规划在这nnn天中,每天买多少块新毛巾、每天送多少块毛巾进行 A 种消毒和每天送多少块毛巾进行 B 种消毒。当然,公司经理希望费用最低。
你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行 A 种消毒和多少毛巾进行 B 种消毒,使公司在这项nnn天的软件开发中,提供毛巾服务的总费用最低。
解析
关键是割点的思想
把每天割成早上和晚上两个点
晚上会得到nin_ini条旧的毛巾
然后按照消毒方式往早上连边
注意当天的毛巾可以留到第二天
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2300;
const int M=2e6+100;
const int mod=998244353;
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();};while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
int n,m,s,t;
struct node{int to,nxt;ll cap,w;
}p[M<<1];
int fi[N],cnt,cur[N];
void addline(int x,int y,ll cap,ll w){p[++cnt]=(node){y,fi[x],cap,w};fi[x]=cnt;p[++cnt]=(node){x,fi[y],0,-w};fi[y]=cnt;
}
ll flow,cost;
queue<int>q;
ll dis[N];
bool vis[N];
bool spfa(){memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));dis[s]=0;q.push(s);bool flag=0;while(!q.empty()){int now=q.front();q.pop();vis[now]=0;for(int i=cur[now]=fi[now];~i;i=p[i].nxt){int to=p[i].to;if(!p[i].cap) continue;if(to==t) flag=1;if(dis[to]>dis[now]+p[i].w){dis[to]=dis[now]+p[i].w;if(!vis[to]){q.push(to);vis[to]=1;}}}}return flag;
}
ll dfs(int x,ll lim){if(x==t||!lim){cost+=lim*dis[t];return lim;}vis[x]=1;ll res=0;for(int &i=cur[x];~i;i=p[i].nxt){int to=p[i].to;if(vis[to]||!p[i].cap||dis[to]!=dis[x]+p[i].w) continue;ll add=dfs(to,min(lim,p[i].cap));res+=add;lim-=add;p[i].cap-=add;p[i^1].cap+=add;if(!lim) break;}if(lim) dis[x]=-1;vis[x]=0;return res;
}
void dinic(){while(spfa()){while(ll tmp=dfs(s,2e18)){flow+=tmp;//printf("tmp=%d\n",tmp);}}return;
}
int x;
int fa,fb,a,b,f;
int main(){memset(fi,-1,sizeof(fi));cnt=-1;n=read();a=read();b=read();f=read();fa=read();fb=read();s=n+1;t=s+1;a++;b++;s=n+n+1;t=n+n+2;for(int i=1;i<=n;i++){x=read();addline(s,i+n,x,0);addline(i,t,x,0);}for(int i=1;i<=n;i++) addline(s,i,2e18,f);for(int i=1;i<n;i++) addline(i+n,i+1+n,2e18,0);for(int i=1;i+a<=n;i++) addline(i+n,i+a,2e18,fa);for(int i=1;i+b<=n;i++) addline(i+n,i+b,2e18,fb);dinic();printf("%lld",cost);return 0;
}