【问题标题】:Algorithm to place a mailbox to minimize the total distance that the residents travel to get their mail放置邮箱以最小化居民获取邮件的总距离的算法
【发布时间】:2017-06-23 16:01:13
【问题描述】:

假设输入被指定为一组建筑物对象,其中每栋建筑物都有一定数量的居民及其与街道起点的距离。

总距离 = SUM(距离[i] * #residents[i])

我在这里发现了两个相似但要求略有不同的问题:

  • Minimizing weighted sum:这道题的解法是找到穿越所有点的最小路径。在这里,我正在寻找从每个建筑物到邮箱所在位置的总距离的最小总和。

  • Minimum Total Distance From Locations:它使用二维坐标,更重要的是,该解决方案没有考虑每个位置的权重(居民数量)。

我在阅读 Elements of Programming Interviews(非常好的书,顺便说一句)时看到了这个问题,这被列为快速选择算法的一种变体。考虑到中位数是最小化距离总和的点,看起来解决方案将涉及快速选择以在 O(N) 中找到位于街道“中位数”位置的建筑物。

但我无法弄清楚如何计算每栋建筑物的居民并仍然保持解决方案线性。

【问题讨论】:

  • 那么邮箱当前是否存在于街道的起点,或者您想找到一个点,如果我们放置邮箱会减少与其他点的距离?
  • 能否发给我这个问题的链接或者告诉我该问题在书中的页码
  • @zenwraight 当然,它的第二个选项,找到一个放置邮箱的地方。在书中,问题是问题 12.9 的最后一个变体 - 找到最大的 kth(我的第 201 页)复制)。我认为谷歌图书预览搜索显示该页面:google.com/…
  • 提示:你想找到一个邮箱位置,每边都有___人。

标签: algorithm linear-programming


【解决方案1】:

我们可以使用增量来确定方向。我会解释我的意思。因为它涉及在其中一栋建筑物(即不在两栋建筑物之间)选择邮箱位置:

选择其中一栋建筑作为枢纽(可能的邮箱位置)。根据建筑物相对于枢轴的位置对建筑物进行分区。分区时,记录枢轴两侧最近的建筑物,以及(1)枢轴两侧的居民总数,以及(2)f(side, pivot)代表每个建筑物的总和到枢纽的距离乘以该建筑物中的居民数量。

现在我们有了:

L pivot R

要确定是否可以对我们的选择进行改进,请尝试我们之前记录的每个最近的建筑物:

如果我们将我们选择的一栋建筑物向左移动,结果会如何变化?我们称左边最近的建筑物为build_l,右边为build_r。因此,将我们选择的一栋建筑物向左移动的新结果是:

左侧:

  f(L, pivot)
- distance(build_l, pivot) * num_residents(build_l)

右侧:

  f(R, pivot) 
  // we saved this earlier
+ total_residents(R) * distance(pivot, build_l)
+ num_residents(pivot) * distance(pivot, build_l)

执行类似的计算,将选择的一栋建筑物向右移动,看看哪个产生的总数较小。然后选择具有改进的建筑物的一侧,并以类似的快速选择方式递归地对其进行分区,直到找到最佳结果。另一方面,我们会跟踪居民总数,以及到目前为止f 的总结果,我们可以随时更新新增内容。

【讨论】:

  • 谢谢@גלעד-ברקן,我也收到了书作者本人的回复,他的建议基本相同。我将此标记为正确的响应。
  • @carlos22 你能在此处发布作者的答案吗,因为该答案不完整 - 没有分析复杂性,也没有解释为什么快速选择比简单通过后处理数组更优化跨度>
  • @PavelPodlipensky 我们实际上并没有使用快速选择。我在参考文献中使用了“类似的快速选择方式”这个词来表示我在过程中看到了相似之处。
  • @גלעדברקן 那么您的方法的时间复杂度是多少?为什么我们需要支点?
  • @PavelPodlipensky 我们需要一个支点,因为 OP 提出的问题似乎是关于如何以与他们正在阅读的书一致的方式解决这个问题,“将 [it] 列为快速选择算法。”
【解决方案2】:

我会用以下方式解决它(下面的伪代码)。

从左到右传递数组并计算所有居民 j 将邮箱放入房屋 i 的成本

# When we place mailbox at building i, all its residents contribute 0 to the total cost.
current_number_of_residents += residents_at_building[i-1]

# For each resident we've seen so far, the cost is increased by building_location[i] - building_location[i-1]
distance_delta = building_location[i] - building_location[i-1]

C_left[i] = C_left[i-1] + distance_delta * current_number_of_residents

然后我们以类似的方式从右到左处理数组。 现在我们可以通过检查最小总和找到最佳位置:

min_total_distance = min(min_total_distance, C_left[i] + C_right[i])

时间复杂度为 O(n),因为我们对数组进行了 3 次遍历。保留 C_left 和 C_right 数组的空间复杂度为 O(n)。

快速选择算法的复杂度(由@גלעד-ברקן 建议)平均也是 O(n),但在最坏的情况下可能是 O(n^2)。所以我看不出这种方法比我建议的方法有什么好处。欢迎任何cmets。

【讨论】:

  • 当 OP 在他们的问题描述中指出问题“在他们正在阅读的书中被列为快速选择算法的变体”时,我认为这意味着他们的问题是关于获得帮助我们如何在这里应用类似的程序。
  • 请至少提供一个解释,如果不能证明,为什么你认为我描述的程序有最坏的情况O(n^2) 复杂性。我不建议使用快速选择。我描述了一个与它有相似之处的过程。
  • @גלעדברקן 我不确定我是否完全理解你的方法,这就是为什么我问你大 O 符号估计。但是我认为它是 O(n^2) 的原因是因为每次选择一个枢轴时,都需要更新左侧 ppl 和右侧 ppl 的加权和,这将花费 O(n) 时间。如果我错了,请纠正我。
猜你喜欢
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多