这道题就是力扣的经典题目“接雨水”了,可以用多种解法来解,这里介绍思路比较简单的dp解法,供大家学习。
首先我们需要考虑到是容器盛装的青豆约束条件,即每一列能装的青豆的状态转移方程。
在上图中以第三列为例,其能盛装的青豆取决于其自身高度和左右两边比它高的边的高度。
在这个例子中,第三列能保存的青豆=min(5,4)-2=2。
我们使用rightmax[]和leftmax[]分别保存右边和左边最高的柱子高度。
从而我们可以得到:
当左右都存在高于当前列的高度的柱子时,res[i] = min(leftmax[i],right[i])-height[i])
至于剩余情况,即左右不同时存在高于当前柱子高度的情况,我们从图中也可以发现可以盛装的青豆数量是为0的。但是如果按照上述方程进行计算,结果可能得到负数,对此我们需要改造一下我们的状态转移方程:
res[i] = max(0, min(rightmax[i], leftmax[i]) - height[i]);
另外在求rightmax[]和leftmax[]时,对于两边边界柱子也要进行特殊处理,在本题中不妨设左边界柱子的rightmax等于其自身,右边界同理,即:
int len = height.size();
leftmax[0] = height[0];
rightmax[len - 1] = height[len - 1];
思路梳理完毕,我们对所给的样例height = [5,0,2,1,4,0,1,0,3]
进行模拟,可得:
leftmax = [5, 5, 5, 5, 5, 5, 5, 5, 5]
rightmax = [5, 4, 4, 4, 4, 3, 3, 3, 3]
res = [0, 4, 2, 3, 0, 3, 2, 3, 0]
最终结果为:17,即为所求。
完整代码如下:
#include <bits/stdc++.h>
using namespace std;
int AccuGreenBeans(vector<int> height)
{
int len = height.size();
vector<int> leftmax(len);
vector<int> rightmax(len);
leftmax[0] = height[0];
rightmax[len - 1] = height[len - 1];
for (int i = 1; i < len; i++)
{
leftmax[i] = max(leftmax[i - 1], height[i]);
}
for (int i = len - 2; i >= 0; i--)
{
rightmax[i] = max(rightmax[i + 1], height[i]);
}
int res = 0;
for (int i = 0; i < len; i++)
{
res += max(0, min(rightmax[i], leftmax[i]) - height[i]);
}
return res;
}
int main()
{
vector<int> height = {5, 0, 2, 1, 4, 0, 1, 0, 3};
int res = AccuGreenBeans(height);
cout << res << endl;
return 0;
}