我最近遇到了一个算法问题,目标是计算在一个建筑宽度为1的城市中产生一定洪水所需的水位高度。
这有点类似于此处描述的二维雨水收集问题:
三维截留雨水的最大体积
然而,在我的问题中,除了建筑物之间的水之外,我们还计算建筑物上方的水。例如,以这个问题为例:
volume needed: 60
number of buildings: 3
heights of buildings: 30 40 20
这意味着我们必须计算所需的水位,这样一个建筑高度为30、40和20的城市,其水量至少为60。
^
|
50 |~~~~~~~~~~~~~|
| | |
40 | ----- |
| | | | |
30 -----| | |
| | || | |
20 | || |-----
| | || || |
10 | || || |
| | || || |
.----------1----2----3---------->
在这种情况下,结果为50,因为水位需要在50的高度,以便建筑物之间和上方的水量至少为60。在这里,每栋建筑上方的洪水分别为20、10和30,加起来正好是60。
我的尝试在时间和正确性方面都表现不佳:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int v;
int n;
cin >> v >> n;
vector<int> altitudes;
int count = 0;
int altitude;
while (count < n) {
cin >> altitude;
altitudes.push_back(altitude);
count++;
}
sort(altitudes.begin(), altitudes.end());
int vtemp = 0;
int i = 1;
int h = altitudes[0];
while (vtemp < v && i < n) {
h++;
if (h == altitudes[i]) {
i++;
}
vtemp = 0;
for (int j = 0; j < i; j++) {
vtemp += h - altitudes[j];
}
}
cout << h << endl;
return 0;
}
当你对建筑物进行分类时,你走在了正确的轨道上。这让我们更清楚地了解每栋建筑上方被困的水层。
例如,假设我们有高度4, 2, 3, 1, 2, 5的建筑物:
x
x x
x x x
xxx xx
xxxxxx
让我们用水把他们淹没。此图使用1表示最底层的水,2表示次底层的水,依此类推:
44444x
x3333x
x2x22x
xxx1xx
xxxxxx
我们可以逐行遍历建筑物以增加水层,直到达到所需的体积。但是,这需要O(nm)
时间,其中n
是建筑物的数量,m
是最大建筑物高度。我们可以做得更好。
让我们把建筑物分类。现在,从左到右的高度为1、2、2、3、4、5:
x
xx
xxx
xxxxx
xxxxxx
再一次,让我们淹没他们:
44444x
3333xx
222xxx
1xxxxx
xxxxxx
现在水层更容易计算。每层的长度是相同高度的建筑数量加上上上一层的长度。
这使我们能够在时间上计算层数,因为我们扫描了一次建筑高度,并对每个建筑执行了固定数量的操作。对建筑物进行排序的成本为O(n log n)。除非m
非常小,否则O(n log n n)
的总成本优于O(nm)
。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int requiredVolume, n;
cin >> requiredVolume >> n;
vector<int> heights;
for (int i = 0; i < n; ++i) {
int height;
cin >> height;
heights.push_back(height);
}
// Sort the buildings by increasing height.
sort(heights.begin(), heights.end());
// Start with the required volume and subtract layers until we reach zero.
int volume = requiredVolume,
waterHeight = heights[0],
layerLength = 0,
pos = 0;
while (volume > 0) {
// Look for the next building that's taller than the current one.
int seek = pos;
while (seek < n && heights[seek] == heights[pos]) {
++seek;
}
// Extend the current water layer.
layerLength += seek - pos;
// Calculate the number of layers we would need to reach zero.
int needLayers = (volume + layerLength - 1) / layerLength;
// If we're at the tallest building, take all the layers we need.
// Otherwise, take layers up to the height of the next building.
int addLayers;
if (seek == n) {
addLayers = needLayers;
} else {
addLayers = min(heights[seek] - heights[pos], needLayers);
}
volume -= addLayers * layerLength;
waterHeight += addLayers;
cout << "with water at height " << waterHeight <<
", the volume is " << (requiredVolume - volume) << '\n';
// Advance to the next building.
pos = seek;
}
cout << "final answer:\n minimum height = " << waterHeight <<
", volume reached = " << (requiredVolume - volume) << '\n';
return 0;
}
对于您在问题中给出的问题实例:
60 3
30 40 20
我们得到以下输出:
with water at height 30, the volume is 10
with water at height 40, the volume is 30
with water at height 50, the volume is 60
final answer:
minimum height = 50, volume reached = 60
如果我们想通过上面示例中的建筑物实现至少11的体积:
11 5
4 2 3 1 2 5
我们得到:
with water at height 2, the volume is 1
with water at height 3, the volume is 4
with water at height 4, the volume is 8
with water at height 5, the volume is 13
final answer:
minimum height = 5, volume reached = 13
将高度从最低到最高排序,然后开始填充最低的,直到其高度等于第二个最低的,然后填充最低的和第二个最低的,直到其高度等于第三个最低的,依此类推,直到水用完。
我在算法中添加了代码注释。我在你的测试数据上进行了测试,效果很好。时间复杂度为O(n log n),因为我们需要对建筑进行排序。没有排序,算法在O(n)中工作
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int v;
int n;
cin >> v >> n;
vector<int> altitudes;
int count = 0;
int altitude;
while (count < n) {
cin >> altitude;
altitudes.push_back(altitude);
count++;
}
sort(altitudes.begin(), altitudes.end());
//-- changed from here
int current_level = altitudes[0]; //start from height of the smallest building
int length = 0;
while (v > 0)
{
++length; //go to next level
for (; length < altitudes.size() && altitudes[length] == altitudes[length - 1]; ++length); //find length of current water level
int height = v / length; //maximum possible height to fill
if (length < altitudes.size()) //if not all building in use
height = min(height, altitudes[length] - current_level); //fill with all water (height) or with the difference to next level
current_level += height; //increase level by height
v -= height * length; //decrease amount of water
if (length == altitudes.size() || v < length) //we filled the whole area, or there is no enough water to fill 1 'meter'
break;
}
cout << current_level << endl;
return 0;
}
我的项目有一个要求。我必须使用水槽收集日志数据,并且必须将数据输入到hive表中。 在这里,我需要将放置在文件夹中的文件收集到hdfs中,我正在使用Spooldir进行。在此之后,我需要处理这些文件并将输出放在hive文件夹中,以便立即查询数据。 我是否可以使用 sink 处理源文件,使放置在 hdfs 中的数据已经处理为所需的格式。? 谢了,萨希
在“分析”菜单栏中点击“淹没模拟”,有绘制多边形和选择面选项,这里演示的是绘制多边形。 在三维地形上绘制一个区域作为模拟分析范围,弹出对话框,设置播放频率以及每次升高高度,在对话框中点击“淹没模拟”按钮,地图上水面开始上升。可以点击“暂停模拟”或“重新模拟”。可在对话框上部查看淹没模拟的最高点、最低点、淹没区域和淹没面积。淹没分析数据来源于内存中分级的DEM,精度有限,
在“分析”菜单栏中点击“淹没模拟”,有绘制多边形和选择面选项,这里演示的是绘制多边形。 在三维地形上绘制一个区域作为模拟分析范围,弹出对话框,设置播放频率以及每次升高高度,在对话框中点击“淹没模拟”按钮,地图上水面开始上升。可以点击“暂停模拟”或“重新模拟”。可在对话框上部查看淹没模拟的最高点、最低点、淹没区域和淹没面积。淹没分析数据来源于内存中分级的DEM,精度有限,
我从Quarkus网站上设置了一个Quarkus/静态编程语言/Gradle项目。我正在尝试使用hibernate/panache/reactive制作一个简单的反应式api: Quarkus 1.13.6。期末考试 API: 型号: 存储库: /事件/你好路径工作正常,但/事件给了我一个错误: 我还有一个警告: application.properties 我找不到这个特定堆栈的适当示例或指南,
问题内容: 我正在尝试使用axis-java2wsdl ant任务从我的一个Java类中创建一个wsdl,但是我无法获得正确的类路径。 我正在使用Ubuntu的libaxis-java软件包,该软件包将$ ant_HOME / lib中的axis-ant.jar和/ usr / share / java中的axis.jar安装。我的build.xml有趣的部分如下所示: 运行结果: Ant可以找到
如何列出Docker容器的所有卷?我知道它应该很容易得到,但我找不到如何得到。 此外,是否可以获取已删除容器的卷并将其删除?