zoukankan      html  css  js  c++  java
  • 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题目翻译也以后再说好了。

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

  • 相关阅读:
    2020/10/29
    2020/10/24
    2020/10/28
    2020/10/31周报
    linux shell 中判断字符串为空的正确方法
    20201107 千锤百炼软工人
    20201103 千锤百炼软工人
    20201109 千锤百炼软工人
    20201111 千锤百炼软工人
    20201105 千锤百炼软工人
  • 原文地址:https://www.cnblogs.com/victbr/p/6507261.html
Copyright © 2011-2022 走看看