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,&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题目翻译也以后再说好了。

  因为原题有三组样例,一开始没考虑到(其实是嫌麻烦),于是就用空行隔开了事。

原文地址:https://www.cnblogs.com/victbr/p/6507261.html