UPC-6206 YLB搭积木(模拟小岛下沉)

题目描述
LCYZ举办了一年一度的“积木大赛”。今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi。
在搭建开始之前,没有任何积木(可以看成n块高度为0的积木)。接下来每次操作,小朋友们可以选择一段连续区间[l,r],然后将第第L块到第R块之间(含第L块和第R块)所有积木的高度分别增加1。
YLB是个智障的小朋友,他想不出使得建造所需的操作次数最少的最佳策略。所以想请你帮他想出这个策略,并求出最少的操作次数。
输入
输入包含两行,第一行包含一个整数n,表示大厦的宽度。
第二行包含n个整数,第i个整数为hi 。
输出
仅一行,即建造所需的最少操作数。
样例输入
5
2 3 4 1 2
样例输出
5
提示
其中一种可行的最佳方案,依次选择
[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。

写这道题的时候突然想起来自己以前写过一个UVALive的水题,说的是小岛下沉,这题做法大概也差不多,当时的数据特别小,只有12,没错,按这题的说法来说宽度仅有12,在此题中已经达到了15000,那么当时的做法在现在是否可取呢? 我尝试找到了那时的代码,做了些修改。果然能用,虽然暴力了些,但是模拟的姿势还是很漂亮的。

总的思路就是拿这个高楼的最终高度,做相反的操作,他问多少操作能提升至输入高度,那么就拿输入高度按操作往下降。每次降高度最低的位置的高度,将每一层沉到位置0。这些最小高度即操作次数累加和。

首先最外层while作为一个重复下沉的循环,当我做了一遍下沉后,检查是否还有高楼存在高度,有的话继续下沉,判断条件就是很暴力的检查数组每一个坐标是否有高度。

第二层循环对宽度做一个遍历,我们将左右为0高度的一整块位置看做一个模块,当遍历到0位置时,将0位置之前的模块做最低高度下沉,然后遍历下一个模块,也就说我们将0高度作为一个模块的开始和结束表示,利用这个标志记录模块开始和结束的坐标。并在模块范围内查找最低高度,然后整体下降。

#include<stdio.h>
#define LL long long
int n,a[100005];
bool check()
{
    for(int i=1;i<=n;i++)
        if(a[i])return false;
    return true;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        LL ans=0;
        while(!check())
        {
            int i=1;
            while(i<=n)
            {
                if(a[i])
                {
                    int minn=0x7fffffff;
                    int st=i;
                    while(a[i]>0)
                    {
                        if(a[i]<minn)minn=a[i];
                        i++;
                    }
                    for(int j=st;j<i;j++)if(a[j])a[j]-=minn;
                    ans+=minn;
                }
                i++;
            }
        }
        printf("%lld\n",ans);
    }
}
posted @ 2018-03-28 01:33  KuroNekonano  阅读(113)  评论(0编辑  收藏  举报