zoukankan      html  css  js  c++  java
  • P3049 [USACO]园林绿化

    绿园林绿化


    Descriptionmathcal{Description}
    有n块土地,每块有A[i]泥土,现把其改造成B[i]泥土,有3种操作:
    (1)花费X向任意土地增加1泥土;
    (2)花费Y向任意土地减少1泥土;
    (3)花费Z*|i-j|把土地i的1泥土运到土地j。问最小花费是多少。

    A[i],B[i]<=100,n<=100,X,Y,Z<=1000A[i],B[i]<=100,\n<=100,\X,Y,Z<=1000


    Solution1mathcal{Solution_1}

    最初想法
    思考发现, 最开始土地分为两种类型 : 要求降低, 要求升高.
    在两个不同类型的土地 i,ji,j 之间, 若 X+Y>ZijX+Y>Z*|i-j| 时, 则将泥土从 ii 搬往 jj 一定优于 直接升高降低.
    于是按照此方法 贪心, 得到 50pts50pts.


    正解部分
    大概思想如上, 是因为我维护方法不对才拿了 50pts50pts, 重点看实现部分.


    实现部分
    对两种类型的土地分别建立两个 大根堆 Q1, Q2Q_1, Q_2, 内部元素是 单位泥土,
    (可以理解为 Q1Q_1 是囤积的泥土, 可以堆到其他土地上; Q2Q_2 是筐, 可以将其他土地上的泥土倒到对应土地上),

    从左往右边扫, 设当前位置为 ii, 土地类型为 要求下降, 即可以将当前泥土堆到其他土地上.
    将该地泥土分为 A[i]A[i] 个单位泥土, 对每个单位泥土 单独处理,

    对当前 要降低 的单位泥土, 有两种选择:

    1. 直接扔泥土, cost=Xcost=X, 此时需要 Q1.push(iZ+X)Q_1.push(i*Z + X)
    2. 从前方不同类型的土地 搬泥土, cost2=iZQ2.top.firstcost_2 = i*Z-Q_2.top.first,
    3. 从后方不同类型的土地 搬泥土,此时需要 Q2.push(iZ+cost2) Q_2.push(i*Z+cost_2)

    注意以上都需执行 Ans+=min(cost,cost2)Ans += min(cost,cost_2)., (弹出操作已省略).

    时间复杂度 O(N10log(N10))O(N*10*log(N*10))
    Solution2mathcal{Solution_2}

    可以使用 DpDp,
    F[i,j]F[i, j] 表示 处理了 ii 个第一类型的单位泥土, jj 个第二类型的单位泥土 所花费的最小价值,

    F[i,j]=min{F[i1,j]+XF[i,j1]+YF[i1,j1]+ZposiposjF[i, j]= minegin{cases} F[i-1, j] + X\ F[i, j-1] + Y\ F[i-1,j-1]+Z*∣pos_i-pos_j∣ end{cases}

    时间复杂度 O((N10)2)O((N*10)^2)


    Codemathcal{Code}
    贪心代码.

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 105;
    const int inf = 0x7f7f7f7f;
    
    int N;
    int X;
    int Y;
    int Z;
    int Ans;
    int A[maxn];
    int B[maxn];
    
    std::priority_queue <int> Q1;
    std::priority_queue <int> Q2;
    
    void Work_1(int i){  // In, Up
            int cost = inf;
            if(!Q1.empty()){
                    int t = Q1.top();
                    int tmp = i*Z - t;
                    if(tmp < X) Q1.pop(), cost = tmp;
            }
            if(cost == inf) cost = X;
            Q2.push(i*Z + cost); Ans += cost;
    }
    
    void Work_2(int i){ // Out, Down
            int cost = inf;
            if(!Q2.empty()){
                    int t = Q2.top();
                    int tmp = i*Z - t;
                    if(tmp < Y) Q2.pop(), cost = tmp;
            }
            if(cost == inf) cost = Y;
            Q1.push(i*Z + cost); Ans += cost;
    }
    
    int main(){
            scanf("%d%d%d%d", &N, &X, &Y, &Z);
            for(reg int i = 1; i <= N; i ++) scanf("%d%d", &A[i], &B[i]);
            for(reg int i = 1; i <= N; i ++)
                    for(reg int j = 1; j <= abs(B[i]-A[i]); j ++)
                            if(A[i] < B[i]) Work_1(i); 
                            else Work_2(i);
            printf("%d
    ", Ans);
            return 0;
    }
    
  • 相关阅读:
    QML Object Attributes QML对象属性
    FindPkgConfig----CMake的pkg-config模块
    如何在linux下制作一个windows的可启动u盘?
    cmake工具链
    sed 命令详解
    说说 bash 的 if 语句
    cmake的四个命令:add_compile_options、add_definitions、target_compile_definitions、build_command
    cmake的命令execute_process
    cmake的两个命令: option 和 configure_file
    linux文件相关的命令
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822592.html
Copyright © 2011-2022 走看看