小明升任了 CF 国的大总管,他管辖的 n 个城市,编号为 1..n。每一个城市生产了 pi 个货物,限制最多能够卖掉 si 个货物。对于每两个城市 i, j,若是 i < j,则能够最多从 i 运送 c 个货物到 j。注意不能反向运送,却能够在多个城市之间送来送去。如今小明想知道,通过运输后,最多能卖掉多少个货物。c++
咱们按照题意试试建图跑网络流?数组
虚构源点和汇点,源点向每一个城市连边容量为pi,每一个城市向汇点连边容量为si,对于全部编号i<j的城市,i向j连边容量为c,跑最大流?网络
但是数据范围决定了,确定开不下,因此咱们得另寻他法。ide
最大流=最小割spa
并且题目里的限制条件很是好,咱们能够直接dp,设f[i][j]表示考虑前i个城市,将其中j个城市分到离源点近的集合,这些点的最小割是多少。咱们只须要枚举对于一个点分在哪一个集合就行了,并且能够开的下滚动数组,时间复杂度也是能够的。code
代码:xml
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=10005; 5 const ll inf=1e14;int n,c; 6 ll f[2][N],p[N],s[N],ans=0,mn; 7 int main(){ 8 scanf("%d%d",&n,&c); 9 for(int i=1;i<=n;i++) 10 scanf("%lld",&p[i]); 11 for(int i=1;i<=n;i++) 12 scanf("%lld",&s[i]); 13 for(int i=1;i<=n;i++){ 14 ans+=min(s[i],p[i]); 15 int x=i&1,y=(i-1)&1; 16 for(int j=0;j<=i;j++){ 17 f[x][j]=inf; 18 if(p[i]>s[i]){//供过于求 19 if(j!=i) f[x][j]=min(f[x][j], 20 f[y][j]+p[i]-s[i]+(ll)j*c); 21 if(j) f[x][j]=min(f[x][j], 22 f[y][j-1]); 23 } else{//供不该求或自产自销 24 if(j!=i) f[x][j]=min(f[x][j], 25 f[y][j]+(ll)j*c); 26 if(j) f[x][j]=min(f[x][j], 27 f[y][j-1]+s[i]-p[i]); 28 } 29 } 30 } mn=f[n&1][0]; 31 for(int i=1;i<=n;i++) mn=min(mn,f[n&1][i]); 32 printf("%lld\n",mn+ans); 33 }