青训营主题创作 攒青豆

109 阅读2分钟

当青训营遇上码上掘金


1.题意分析

1.1简单模型 只有两面墙构成的水池

其接水量是两面墙体中最矮的决定的,结果是水池宽度乘以矮墙高度。

1.2真实情形

与模型的联系:真正的水池完全可以看成是许多墙体彼此依靠共用其边来创造的N多水池。

与模型的区别:各个小水池的双边高度不好获取,若是依次按照水池获得左右双边的高度一定效率低下。

进一步思考后:由于每个小水池都有与其它小水池公用的边,若能将每个小水池的边仅获取一遍,就能解决效率问题。

最后的方案是:(双指针) 将整个水池看成一个水池,得到其左右墙的高度,比较高度,从矮墙一侧开始记录水量,直到遇到比矮墙高的墙就停下,再次得到现在的左右墙,再次记录水量。直到左右墙合并了(边界条件)。

进行一定的论证:对于整个水池和他的左右墙,其水量一定不小于 水池宽度乘以矮墙高度 ,若其中不存在比矮墙高的墙,则水量计算公式没有问题,若其中存在比矮墙高的墙,则将已经计算的部分划为一个小水池,将未计算的部分再次视作一个水池则能计算完成。

注意:边界条件要分析清楚

2.代码

//青训营 X 码上掘金 主题4 code
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> height;
    int t;
    while (cin >> t)
        height.push_back(t);
    int leftPointer = 0;
    int rightPointer = height.size() - 1;
    int leftWall = height[leftPointer];
    int rightWall = height[rightPointer];
    int sum = 0;

    // 获得第一道左墙
    while (leftWall == 0)
    {
        leftPointer++;
        // 超界
        if (leftPointer >= height.size())
            break;
        leftWall = height[leftPointer];
    }

    // 获得第一道右墙
    while (rightWall == 0)
    {
        rightPointer--;
        // 超界
        if (rightPointer < 0)
            break;
        rightWall = height[rightPointer];
    }

    while (rightPointer > leftPointer)
    {
        // 从矮墙开始接豆
        if (leftWall < rightWall)
        {
            while (leftWall >= height[leftPointer])
            {
                // 接完豆了
                if (rightPointer == leftPointer)
                    break;
                sum += leftWall - height[leftPointer];
                leftPointer++;
            }
            leftWall = height[leftPointer];
        }
        else
        {
            while (rightWall >= height[rightPointer])
            {
                // 接完豆了
                if (rightPointer == leftPointer)
                    break;
                sum += rightWall - height[rightPointer];
                rightPointer--;
            }
            rightWall = height[rightPointer];
        }
    }
    cout << sum;
}