码上掘金活动主题四

59 阅读1分钟

当青训营遇上码上掘金,码上掘金作为青训营伴随的众多活动之一,帮助激发大家的求学兴趣和实践能力,这里我选择主题四实现

题目如下:

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积) image.png

测试样例:

以下为上图例子的解析: 

输入:height = [5,0,2,1,4,0,1,0,3] 
输出:17 
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

解题思路

  • 首先,把柱子和青豆存储区域都看成单位面积的矩形就可以将其转换为几何问题,一些不同高度的矩形最多能围成多少个单位面积用于储存青豆。
  • 根据观察可以知道这个面积的形成取决于较高的几根柱子,以第一根柱子的高度为基准,从第二根开始往后找高度最高的柱子:

这里用top1指代第二根柱子起最高的柱子下标

height(index)代表对应下标柱子的高度

sum(index)代表前index个柱子的高度和

  • height(top1) >= height(0)时,决定围成面积高度的是短一点的柱子即height(0),若height(top1) < height(0),则决定高度的是height(top1),将起决定作用的高度记为H;
  • sum(index2-1)-sum(index1)的值就是index1和index2之间柱子累加的面积S
  • 再用H*(index2-index1-1)-S就得到第一根柱子与top1位置的柱子围成的单位面积

image.png

sum(0)sum(1)sum(2)sum(3)sum(4)sum(5)sum(6)sum(7)sum(8)
55781212131316
  • 然后以top1位置的柱子高度为基准,寻找top1位置之后最高的柱子top2,也像以上方式来计算围成面积,直到计算至最后一根柱子,将得到的面积累加就是我们要求的总单位面积,也就是青豆数

代码实现

#include <iostream>

using namespace std;

int getHighest(int x,int y,int *array){
    int top = x;
    for(int i = x+1 ; i < y ; i++){
        if(array[top] <= array[i]) top = i;
    }
    return top;
}

int main(){
    int height[100],a,i=0,area=0;
    int sum[100] = {0};
    while(cin>>a){
        height[i] = a;
        cout<<i<<"\t"<<height[i]<<"\t";
        if(i == 0)sum[i] = height[i];
        else{ sum[i] = sum[i-1] + height[i];}
        cout<<sum[i]<<endl;
        i++;
        if(cin.get()=='\n') break;
    }
    int n = i;
    cout<<"n="<<n<<endl;
    int top,top_next;
    top = 0;
    while(top_next != n-1){
        top_next = getHighest(top+1,n,height);
        int H = height[top] <= height[top_next]?  height[top]:height[top_next];
        area += H*(top_next-top-1) - (sum[top_next-1]-sum[top]);
        top = top_next;
    }cout<<"We can save "<<area<<" QingDou!"<<endl;
    return 0;
}

题目所给示例运行结果如下:

image.png

另一示例:

输出结果为:

image.png