题意:
一家餐厅第 i i i 天需要 r i r_i ri张餐巾,每天餐巾用完后就会变脏,对于餐巾可以
- 买一条新的,费用 p
- 送到快洗店,m 天后送回来,费用 f
- 送到满洗店,n 天后送回来,费用 s
- 把脏餐巾留着到以后再洗
题解:
把每一天拆成两个点——早上和晚上,早上接收新餐巾,晚上接收脏餐巾,可以这样建图
- 源点 S —> 第 i i i 天早上,流量 INF,费用 p(因为早上可以买无数条)
- 第 i i i 天早上 —> 汇点 T,流量 r[i],费用 0(表示这一天的结束)
- 源点 S —> 第 i i i 天晚上,流量 r[i] ,费用 0(晚上收到脏餐巾)
- 第 i i i 天晚上 —> 第 i + m i+m i+m天早上,流量 INF,费用f(快洗)
- 第 i i i 天晚上 —> 第 i + n i+n i+n天早上,流量 INF,费用s(慢洗)
- 第 i i i 天晚上 —> 第 i + 1 i+1 i+1天晚上,流量 INF,费用0(把脏餐巾留到下一天)
对于样例的图就是这样的
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;
#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
const int mod = 1e9+7;
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
struct node{
int to,next;
int cap,cost;
}e[N];
int head[N],cnt=-1,S,T;
void add(int u,int v,int cap,int cost){
e[++cnt]={v,head[u],cap,cost}; head[u]=cnt; swap(u,v);
e[++cnt]={v,head[u],0,-cost}; head[u]=cnt;
}
int r[2005],p,m,f,n,s,a;
int mincost,maxflow,dis[5005],flw[5005],pre[5005],vis[5005];
bool spfa(){
memset(dis,-1,sizeof dis);
memset(vis,0,sizeof vis);
dis[S]=0,flw[S]=INF,vis[S]=1,pre[S]=-1;
queue<int>q;
q.push(S);
while(!q.empty()){
int u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(!e[i].cap)continue;
if(!~dis[v]||dis[v]>dis[u]+e[i].cost){
dis[v]=dis[u]+e[i].cost;
flw[v]=min(flw[u],e[i].cap);
pre[v]=i;
if(!vis[v])q.push(v),vis[v]=1;
}
}
}
return ~dis[T];
}
void update(){
for(int i=pre[T];~i;i=pre[e[i^1].to])
e[i].cap-=flw[T],e[i^1].cap+=flw[T];
maxflow+=flw[T];
mincost+=dis[T]*flw[T];
}
#define endl '\n'
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
memset(head,-1,sizeof head);
cin>>a;
S=2*a+1,T=2*a+2; //源点S,汇点T
for(int i=1;i<=a;i++)cin>>r[i];
cin>>p>>m>>f>>n>>s;
for(int i=1;i<=a;i++){
add(S,i+a,r[i],0); //情况1
add(i,T,r[i],0); //情况2
add(S,i,INF,p); //情况3
if(i+m<=a)add(i+a,i+m,INF,f); //情况4
if(i+n<=a)add(i+a,i+n,INF,s); //情况5
if(i+1<=a)add(i+a,i+a+1,INF,0);//情况6
}
while(spfa())update();//费用流板子
cout<<mincost<<endl;
}