P3049 [USACO12MAR]园林绿化Landscaping

贪心啦贪心,好久没 贪心啦~

这道园林绿化教你做人啦~

题目描述

Farmer John is building a nicely-landscaped garden, and needs to move a large amount of dirt in the process.

The garden consists of a sequence of N flowerbeds (1 <= N <= 100), where flowerbed i initially contains A_i units of dirt. Farmer John would like to re-landscape the garden so that each flowerbed i instead contains B_i units of dirt. The A_i's and B_i's are all integers in the range 0..10.

To landscape the garden, Farmer John has several options: he can purchase one unit of dirt and place it in a flowerbed of his choice for XX. He can remove one unit of dirt from a flowerbed of his choice and have it shipped away for YY. He can also transport one unit of dirt from flowerbed i to flowerbed j at a cost of ZZ times |i-j|. Please compute the minimum total cost for Farmer John to complete his landscaping project.

输入输出格式

输入格式:

* Line 1: Space-separated integers N, X, Y, and Z (0 <= X, Y, Z <= 1000).

* Lines 2..1+N: Line i+1 contains the space-separated integers A_i and B_i.

输出格式:

* Line 1: A single integer giving the minimum cost for Farmer John's landscaping project.

说明

There are 4 flowerbeds in a row, initially with 1, 2, 3, and 4 units of dirt. Farmer John wishes to transform them so they have 4, 3, 2, and 0 units of dirt, respectively. The costs for adding, removing, and transporting dirt are 100, 200, and 1.

One unit of dirt must be removed (from flowerbed #4), at a cost of 200. The remaining dirt can be moved at a cost of 10 (3 units from flowerbed #4 to flowerbed #1, 1 unit from flowerbed #3 to flowerbed #2).


  开玩笑的啦,怎么可能真的是英文题面啊?

中文题面

  有n块土地,每块有A[i]泥土,现把其改造成B[i]泥土,有3种操作:

    (1)花费X向任意土地增加1泥土;

    (2)花费Y向任意土地减少1泥土;

    (3)花费Z*|i-j|把土地i的1泥土运到土地j。问最小花费是多少。


 思路分析

  首先看到对于每一块地都有三种操作,最后求取最小值,是不是第一反应就是DP啊?

  那么我们不妨来思考一个问题:

    假设转移的费用远远要小于购买或者卖掉 【相当于0.00000000000000001与100000000000000000000的区别

    此时对于一块需要加土的土地来说,

        如果能够转移的土地在很遥远的地方,远到转移比购买花费还大,怎么判断?

        如果能够转移的土地一块不够转移怎么办?

        如果转移了这一块,但是下一块要满足的话,代价会很大怎么办?

  那么显然这个时候采取动态规划就不太方便了。

  这个时候怎么办呢?

  其实对于这个问题无非就是 想买/卖,但是到后来又发现其实转移更合适一点,要怎么修改的问题。

  那么我们不妨直接了当的选取当前的最优解,同时存储下来另一个解与当前值的差值,方便之后修改。

  所以思路就显而易见了 啊。。。

    首先开两个大根堆,分别存储需要增加的土,和空余的地。

    然后对于每一个点走一次可反悔的贪心就好了。

  但是,这种做法并没有回答刚刚的所有疑问。

    如果一块不够转移怎么办?

    从另一块转移的话,那么这个大根堆不仅要维护和当前点的位置,还要维护数量............【太高级了吧,我觉得不好办

  那么我们就需要一个可以规避这种问题的方法。

    仔细想想,可以发现造成大根堆维护困难的原因不就是需要的单位面积不同嘛?

    那么我们不妨将每一块土地分割成单位面积,这样的话就没有维护数量的事情了。

    我们只要在使用之后把它pop掉就可以了。

          比如5块土地,1缺1,2缺1,3多1,4多5,5缺1

        就拆成   第一个堆 1 2 2 5        这样。

            第二个堆 3 4 4 4 4 4 

  看似没有什么问题了。。。

  等等还没完。。

    如果被转移走的那个位置忽然发现其实不是最优的怎么办???

  这个也好解决啊。

    既然刚刚已经反悔过一次了,那么我们不如就直接把反悔的部分当作一种梦想,

    相当于虚构出来一块这样的土地。

      感性理解一下,比如我这块土地x缺少1 ,土地y多余1,【只是瞎举的例子,可能不合理

              我就直接假装把y的1给了x,但是y那里还认为自己多余1,然后在存储缺少1的堆里加上一个y

      如此就是一次梦想操作。

  基本上没什么问题了,具体代码实现细节自己体悟吧。


代码实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;

const int inf=0x7f7f7f7f;
int n,x,y,z;
int ans;
priority_queue<int> a;//囤积的泥土 
priority_queue<int> b;//缺土的地 

void JIA(int nw) {
    int cost=inf;
    if(!a.empty()) {
        if(nw*z-a.top()<x) {
            cost=nw*z-a.top();
            a.pop();
            b.push(nw*z+cost);
        } 
    }
    if(cost==inf) {
        cost=x;
        b.push(nw*z+cost);
    }
    ans+=cost;
    return;
}

void JIAN(int nw) {
    int cost=inf;
    if(!b.empty()) {
        if(nw*z-b.top()<y) {
            cost=nw*z-b.top();
            b.pop();
            a.push(nw*z+cost);
        }
    }
    if(cost==inf) {
        cost=y;
        a.push(nw*z+cost);
    }
    ans+=cost;
    return;
}

void pd(int nw,int m) {
    if(m<0) {
        JIA(nw);
        return;
    }
    JIAN(nw);
    return;
}

int main()
{
    scanf("%d",&n);
    scanf("%d%d%d",&x,&y,&z);
    for(int i=1;i<=n;i++) {
        int c,d;
        scanf("%d%d",&c,&d);
        for(int j=1;j<=abs(c-d);j++)
            pd(i,c-d);
    }
    cout<<ans<<endl;
    return 0;
}

谢谢,祝AC!

posted @ 2019-07-15 18:13  鸽子咕  阅读(218)  评论(0编辑  收藏  举报