2019深信服校招——木板接水

2019深信服校招——木板接水

题目描述

       空地上竖立着n个从左到右排列的木板,它们可以把水挡住,但溢出最边上木板的水将会流到空地上。已知木板间距都是单位1,现给定每个木板的高度,请求出总共能接住的水量?说明一点,这里只考虑间距(宽度)和高度,不考虑第三个维度,因此水量是平方单位。  

       示例1,木板高度分别是2,1,3,那么我们可以接住2*2=4平方单位的水,如下图所示。注意,中间那个木板被水淹没了。

       示例2,木板高度分别是2,4,3,那么可以接住2*1+3*1=5平方单位的水,如下图所示。

2019深信服校招——木板接水_第1张图片

2019深信服校招——木板接水_第2张图片

思路:不断降低所有木板高度 (如图)

       (1) 先找到左右两端木板高度的较小值minHeight=min(ivec[0],ivec[size-1]) (ivec中存放排列的木板高度),求出这部分容量volume=(size-1)*miniHeight;

       (2) 将所有木板长度减去minHeight,得到新的排列木板序列,定义两个指针low、high,分别从左右开始遍历数组ivec,找到左右两端第一个高度大于0的木板,此时minHeight=min(ivec[low],ivec[high]), volume=(high-low)*minHeight;故总共能接住的总量sum += volume;(每次容量相加)

       (3) 重复步骤2,直至木板序列中只有一块木板高度大于0或全部木板高度均小于0,则此时sum为最大容量。

2019深信服校招——木板接水_第3张图片

#include 
#include 
#include 

using namespace std;

void sub(vector &ivec, int &height)
{
	for (auto &m : ivec)
		m -= height;
}

int getVolume(vector &ivec, int &low, int &high, int &height)
{
	int size = ivec.size();
	int volume = 0;
	for (; low < size; low++)
	{
		if (ivec[low]>0)
			break;
	}
	for (; high >= 0; high--)
	{
		if (ivec[high]>0)
			break;
	}
	if (low < size && high < size)
	{
		height = min(ivec[high], ivec[low]);
		volume = (high - low)*height;
	}
	return volume;
}

int main()
{
	int t;
	cin >> t; 
	while (t--)
	{
		int n;
		cin >> n;
		vector ivec(n, 0);
		for (auto &m : ivec)
			cin >> m;
		int sum = 0;
		int size = ivec.size();
		int low = 0; 
		int high = size - 1;
		int height = min(ivec[low], ivec[high]);
		int volume = getVolume(ivec, low, high, height);
		while (low < size && high < size && ivec[low] > 0 && ivec[high] > 0)
		{
			sum += volume;
			sub(ivec, height);
			volume = getVolume(ivec, low, high, height);
		}
		cout << sum << endl;
	}
	return 0;
}

 

你可能感兴趣的:(笔试题)