luogu P1969积木大赛(NOIP 2013 TG)

题目描述

春春幼儿园举办了一年一度的“积木大赛”。今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi。

在搭建开始之前,没有任何积木(可以看成n块高度为 0 的积木)。接下来每次操作,小朋友们可以选择一段连续区间[l, r],然后将第第 L 块到第 R 块之间(含第 L 块和第 R 块)所有积木的高度分别增加1。

小 M 是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少。但她不是一个勤于动手的孩子,所以想请你帮忙实现这个策略,并求出最少的操作次数。

输入格式:
输入文件为 block.in

输入包含两行,第一行包含一个整数n,表示大厦的宽度。

第二行包含n个整数,第i个整数为hi 。

输出格式:
输出文件为 block.out

仅一行,即建造所需的最少操作数。

说明

【样例解释】

其中一种可行的最佳方案,依次选择

[1,5] [1,3] [2,3] [3,3] [5,5]

【数据范围】

对于 30%的数据,有1 ≤ n ≤ 10;

对于 70%的数据,有1 ≤ n ≤ 1000;

对于 100%的数据,有1 ≤ n ≤ 100000,0 ≤ hi≤ 10000。

这种裸的贪心题一般是没有什么思维难度。贪心题求解的一般步骤:结合数据范围与题意,想出几种可能的贪心策略,分别尝试证明,当然绝大多数的贪心策略是无法很快想到证明方法的,把握一个重点:选择的贪心策略一定尽可能保证每一次贪心都无后效性;
当然,考场上“贪心只会猜题意也是一种得分(暴力)策略”


来看题,乍一看貌似还是很可做的,但是数据范围好像不太好处理,假如说暴力求解,那大概是从头开始枚举,O(n^2)的暴力还是蛮好想的,当然稳稳的超时,这时候我们就要开始思考(口胡),有没有一种线性或者logn做法呢?归并排序求逆序对?这是我刚开始想的方法,当然完全是扯淡,没有任何依据。那么我们回归上面提到的重点:选择的贪心策略一定尽可能保证每一次贪心都无后效性。好的,读了两遍以后貌似有了点眉目?我们是否可以只比较相邻的两块的高度差,逐步往后推?
不知道对不对,那么试着画图看看?
这里写图片描述
这是我们目标中的建筑,我们可以倒推,因为搭建的最少次数=拆卸的最少次数。按照我们的猜想分析:
1.首先看第一部分,我们可以认为它前一部分高度为0,那么我们当前搭建的最少次数是2(搭建一层就是一次)
2.观察第二部分与第一部分,我们能够知道,在搭建第一部分是我们就可以完成第二部分的前两层,那么第二部分只需要再搭一层即可
3.继续观察,发现搭建第三部分前,在搭建第一二部分是我们就可以完成第三部分的前三层,所以第三部分我们仍只需搭一层
4.前三部分的楼高都成递增趋势,那突然来一个比前一层低的情况怎么解决?很简单,我们在搭建前棉三部分时必然能够直接搭建好这一部分,无需再考虑
5.最后一部分呢?又开始递增,那么能否再与前面的四部分相连?显然不行,那么在搭建前四部分时,显然第五部分只能被搭建好第一层,即任意在搭建哪一部分时,都可以也都只能搭建好第五部分第一层。那么我们只能考虑第四五部分之间的关系,即搭建好第四部分开始完善第五部分时只需要再加一层就好了
好像还是很靠谱的!!!
我们的贪心策略:只考虑相邻的楼高关系,逐步分解


#include <iostream>
using namespace std;
int n,h,last,cnt;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>h;
        if(h>last) cnt+=(h-last),last=h;
        else last=h;
    }
    cout<<cnt;
    return 0;
}

这里只是展示了一下简单贪心的策略制定方法,贪心的应用当然不可能这么简单,它会与众多算法相结合,还要多加练习!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值