题意:
一个国家有n个城市,生产同一种商品,已知城市i生产该商品pi件,能销售该商品si件,且每个城市i能够向编号大于它的任意一个城市运送不超过c单位的商品,将这种操作描述为(i,j),每个(i,j)最多发生一次
solution:
很容易想到网络流,图构建出来发现边数是O(n^2)的,,不用玩了--
事实上网络流跑这个的实质,是求出一个最大流,也就是最优方案,,而这个最大流,在数值上是等于最小割的
如果我们想到一个更好的办法,求解出该最小割,问题也就解决了
原本的构图,是源点向每个点连容量为pi的边,每个点向汇点连容量为si的边,对于一个点i,向(i,n]每个点连容量为c的边
从小到大考虑每个点
一个点想要放在s-割,只需要断掉它连到汇点的边即可
一个点想要放在t-割,除了要断掉源点到它的边,还涉及到前面的决策
前面有多少个点在s-割,就要断掉多少条容量为c的边
发现,,,这个东西,只和前面有多少点选择在s-割有关,而与是哪些点在s-割无关
fi,j:前i个点选择了j个点在s-割,最小代价
暴力dp之,问题解决--
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
typedef long long LL;
const int maxn = 1E4 + 10;
const LL INF = 1E16;
int n,cur,s[maxn],t[maxn];
LL c,f[2][maxn];
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n >> c;
for (int i = 1; i <= n; i++) scanf("%d",&s[i]);
for (int i = 1; i <= n; i++) scanf("%d",&t[i]);
for (int i = 1; i <= n; i++) {
f[cur^1][i] = INF;
for (int j = 1; j <= i; j++)
f[cur][j] = min(f[cur^1][j] + s[i] + 1LL*j*c,f[cur^1][j-1] + t[i]);
f[cur][0] = f[cur^1][0] + s[i];
cur ^= 1;
}
LL Ans = INF;
cur ^= 1;
for (int i = 0; i <= n; i++) Ans = min(Ans,f[cur][i]);
cout << Ans;
return 0;
}