这题好神呀。
首先这是一个网络流模型,考虑每个点都向编号比它大的点连一条容量为c的边,然后如果
但是这个图太大了,不能直接跑最大流,也无法优化。
所以我们可以转而考虑最小割,我们发现如果我们知道了割中的点是哪些,其实是可以直接算出割的大小的。
所以如果设f(i,j)表示前i个点,S中有j个的最小割。那么
代码:
#include<stdio.h>
#include<iostream>
using namespace std;
#include<algorithm>
const int N=1e4+5;
int p[N],s[N];
typedef long long LL;
LL f[N];
int main()
{
//cout<<(sizeof(rest)>>20)<<endl;
//freopen("cf724e.in","r",stdin);
int n,c;
scanf("%d%d",&n,&c);
for(int i=1;i<=n;++i)scanf("%d",p+i);
for(int i=1;i<=n;++i)scanf("%d",s+i);
LL ans=0;
for(int i=1;i<=n;++i)
{
ans+=min(s[i],p[i]);
if(s[i]<=p[i])f[i]=f[i-1];
else f[i]=f[i-1]+s[i]-p[i];
for(int j=i-1;j>=0;--j)
if(s[i]<=p[i])
{
f[j]+=p[i]-s[i]+(LL)j*c;
if(j)f[j]=min(f[j],f[j-1]);
}
else{
f[j]+=(LL)j*c;
if(j)f[j]=min(f[j],f[j-1]+s[i]-p[i]);
}
//for(int j=0;j<=i;++j)printf("f(%d,%d)=%I64d\n",i,j,f[j]);
}
cout<<(ans+*min_element(f,f+n+1))<<endl;
}
总结:
①。。感觉经常想不到网络流呢。什么样的题要用网络流呢?也许是方案非常复杂的那种吧,就像这道题。所以如果感觉方案很鬼畜难以统计就考虑一下网络流吧!
②注意最大流与最小割的转化。