由于太久没有打费用流导致我第一眼以为是DP。。。
这就是裸的费用流,先把每个月看作一个点.
然后
S到每个点i,连容量为inf,费用为单价的边
每个点i到T,连容量为需求,费用为0的边。
最后每一个点连向下一个点,费用为m,容量为s,这个很好理解吧。
然后跑一边费用流就好了。
//定义的数组名字意思和实际意思不同搞得我很难受= =
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define T 2001
using namespace std;
const int N=1e5+5;
const int inf=0x7fffffff;
int from[N],tot=1,q[N],dis[N],from1[N];
int head[N],go[N],next[N],val[N],cap[N];
bool inq[N];
int n,m,s,ans;
inline void add(int x,int y,int w,int c)
{
go[++tot]=y;
from[tot]=x;
val[tot]=w;
cap[tot]=c;
next[tot]=head[x];
head[x]=tot;
}
inline void ins(int x,int y,int w,int c)
{
add(x,y,w,c);
add(y,x,0,-c);
}
inline bool spfa()
{
for(int i=0;i<=T;i++)dis[i]=inf;
int t=0,w=1;
dis[0]=q[1]=0;
inq[0]=1;
while (t<w)
{
int x=q[++t];
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (val[i]&&dis[v]>dis[x]+cap[i])
{
from1[v]=i;
dis[v]=dis[x]+cap[i];
if (!inq[v])
{
inq[v]=1;
q[++w]=v;
}
}
}
inq[x]=0;
}
if (dis[T]==inf)return 0;
return 1;
}
inline void mcf()
{
int i,x=inf;
for(int i=from1[T];i;i=from1[from[i]])
{
x=min(val[i],x);
}
i=from1[T];
while (i)
{
val[i]-=x;
val[i^1]+=x;
ans+=x*cap[i];
i=from1[from[i]];
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
fo(i,1,n)
{
int x;
scanf("%d",&x);
ins(i,T,x,0);
}
fo(i,1,n)
{
int x;
scanf("%d",&x);
ins(0,i,inf,x);
}
fo(i,1,n-1)ins(i,i+1,s,m);
while (spfa())mcf();
printf("%d\n",ans);
return 0;
}