Goods transportation
题目来源:codeforces 724E
Description
There are n cities located along the one-way road. Cities are numbered from 1 to n in the direction of the road.
The i-th city had produced pi units of goods. No more than si units of goods can be sold in the i-th city.
For each pair of cities i and j such that 1 ≤ i < j ≤ n you can no more than once transport no more than c units of goods from the city i to the city j. Note that goods can only be transported from a city with a lesser index to the city with a larger index. You can transport goods between cities in any order.
Determine the maximum number of produced goods that can be sold in total in all the cities after a sequence of transportations.
Input
The first line of the input contains two integers n and c (1 ≤ n ≤ 10 000, 0 ≤ c ≤ 109) — the number of cities and the maximum amount of goods for a single transportation.
The second line contains n integers pi (0 ≤ pi ≤ 109) — the number of units of goods that were produced in each city.
The third line of input contains n integers si (0 ≤ si ≤ 109) — the number of units of goods that can be sold in each city.
Output
Print the maximum total number of produced goods that can be sold in all cities after a sequence of transportations.
Sample Input
3 0
1 2 3
3 2 1
5 1
7 4 2 1 0
1 2 3 4 5
4 3
13 10 7 4
4 7 10 13
Sample Output
4
12
34
解题思路
首先考虑暴力,直接跑最大流。这显然是过不了的。由于最大流等于最小割。于是我们可以将原问题转换为在建好的最大流图上求最小割。考虑当前做到第i个点,之前有j个点跟S相连。那么接下来的转移要么割掉i->T,跟S相连的点个数加一;要么割掉S->i和p_j->i,跟S相连的点个数不变。
注意:不能同时割S->i和i->T,因为这样i还是和S联通,还不如只割i->T。数据范围较大,需要滚动数组。
时间复杂度O(n^2)。
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 10100; ll ans,c,f[N],g[N],INF; int n,p[N],s[N]; int main(){ INF = 0x3fffffffffffffff;ans = INF; scanf("%d%I64d\n",&n,&c); for (int i = 1;i <= n;i++) scanf("%d",&p[i]); for (int i = 1;i <= n;i++) scanf("%d",&s[i]); for (int i = 1;i <= n;i++){ f[0] = g[0]+p[i]; for (int j = 1;j <= i;j++) f[j] = min(g[j-1]+s[i],g[j]+p[i]+c*j); for (int j = 0;j <= i;j++) g[j] = f[j]; g[i+1] = INF; } for (int i = 0;i <= n;i++) ans = min(ans,f[i]); cout << ans; return 0; }
后记
感觉可能配图会更清楚一些,然而懒癌发作orz题目翻译也以后再说好了。
因为原题有三组样例,一开始没考虑到(其实是嫌麻烦),于是就用空行隔开了事。