先考虑一种网络流解法,从源点 (S) 向每个点连容量为 (p_i) 的边,每个点向汇点连容量为 (s_i) 的边,每个点向编号比其大的点连容量为 (c) 的边,该图的最大流即为答案。
但是复杂度无法接受,考虑换一种思路,观察建出的图:
发现这张图比较特殊,像最小割的模型,考虑将求最大流转为求最小割,用考虑 (DP) 来解决。设 (f_{i,j}) 为考虑了前 (i) 个点,有 (j) 个点与源点相连的最小割花费,得转移方程为:
[large f_{i,j}=minleft(f_{i-1,j-1}+s_i,f_{i-1,j}+p_i+jc
ight)
]
即转移为点 (i) 是和源点相连还是和汇点相连。(DP) 数组开不下,需要用滚动数组。
#include<bits/stdc++.h>
#define maxn 10010
#define inf 10000000000000000
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
ll n,c,x,ans=inf;
ll p[maxn],s[maxn],f[2][maxn];
int main()
{
read(n),read(c);
for(int i=1;i<=n;++i) read(p[i]);
for(int i=1;i<=n;++i) read(s[i]);
for(int i=1;i<=n;++i,x^=1)
{
f[x][0]=f[x^1][0]+p[i];
for(int j=1;j<=n;++j) f[x][j]=inf;
for(int j=1;j<=i;++j)
f[x][j]=min(f[x^1][j-1]+s[i],f[x^1][j]+p[i]+j*c);
}
for(int i=0;i<=n;++i) ans=min(ans,f[x^1][i]);
printf("%lld",ans);
return 0;
}