【问题标题】:Networking Algorithm to Maximum a Subset of Integers最大化整数子集的网络算法
【发布时间】:2014-12-12 08:49:15
【问题描述】:

我目前正在从事一个模拟几种不同类型网络的宠物项目。其中之一需要一些特定的条件,直到现在我只是蛮力的。然而,它的扩展性并不好,所以我试图有效地做到这一点,但这个算法真的让我很难过!我会尽量概括地描述这个问题。

给定一组整数 X 和一个整数 k,找到 X 的一个子集 Y,它在 X 中的每个值上最大化 M 的总和:

M(s) = Y 中小于或等于 s 的最大值。

例如,对于 {2, 4, 5} 和 k = 2,解是 {2, 4},其值为 2+4+4=10,因为 M(2) = 2, M(4) = 4,和 M(5) = 5。

我的直觉是解决方案是一种动态编程算法,但我可能还差得很远。任何帮助将不胜感激!

【问题讨论】:

    标签: algorithm networking dynamic-programming


    【解决方案1】:

    这是一个带有解决方案的动态程序问题 - 我不确定它是否是你的,因为我不确定你所写内容的细节,但它可能是。

    对一组数字进行排序并绘制一条曲线,其中 x 轴给出排序顺序中数字的偏移量,y 轴给出数字。曲线下会有一些区域。

    您的点数是有限的,通常比集合中的成员少。您可以使用这些点中的每一个来标记集合中的一个点,从而标记曲线上的一个点。

    在曲线下绘制直方图。在每个标记点处,都有一条从该点向右延伸的线,因此这些线完全位于曲线下方。每条这样的线一直延伸到它到达下一个标记点​​的 x 值,此时有一条线向上延伸到新的标记点。

    接下来的挑战是选择要标记的点,以最大化从标记点开始的水平线下方的区域。这是直接的动态规划。如果您最多可以选择 k 个标记点,则在直方图的每个点上,使用 0、1、2、..k 个标记点(可能包括该点)计算出该点左侧可以覆盖的最大区域。你可以通过参考你已经为它左边的点计算出的答案来计算出每个点的答案。最右边点的答案就是整个问题的答案。

    为了扩展这一点:假设您正在制定以偏移量 10 结束的最大面积的最佳解决方案。对于 0..k 的每个值 j,请考虑采用以 0、1、2、3 结束的先前最佳解决方案... 9 并保持该点的高度,而不引入新行。总面积是直到该点的面积加上他们在该点的任何高度获得的新面积乘以返回该点的距离。也可以考虑这样做,但在该点使用一个额外的标记点,所以总面积是 j-1 点的最佳解决方案的面积,例如点 7 加上从点 10 到点 7 的距离乘以点 7 达到的高度。通过考虑这两种可能性,您可以使用 0、1、2、...k 个标记点在点 10 处找出最佳解决方案。

    我认为这些问题是相关的,因为对于每个点,无论是否标记,它对直方图的贡献取决于其上方线的高度,即最大标记点的高度不大于我们的点目前正在考虑中。

    为此,您需要一个 kn 元素数组,在每个点上使用最多 k 个标记点给出最佳解决方案所覆盖的区域。使用这种大小的额外数组来记录导致此最佳解决方案的决定也很方便,因此您可以追溯答案。这需要大约 kn^2 的成本,因为在 n 个点中的每一个点上,您都需要计算 k 个值,并在执行此操作时回顾所有先前的点。我怀疑您可以通过更改您在每个点存储的内容的定义来将其减少到 O(kn) 之类的东西,这样您就不必再回头看前一点了。如果你能做到这一点,你可以通过只存储几个中间点并在较小的部分上重新解决问题以追溯,以节省时间为代价节省存储空间,但你需要极度缺乏存储空间才能做到这一点值得。

    【讨论】:

    • 这绝对是同一个问题,谢谢!对此的视觉解释真的很酷。我对解决方案有疑问。我们需要一个包含 nk 个元素的表还是只需要一个包含 n 个元素的数组? “最右边的点”似乎暗示了一个数组。
    • 另外,您还有其他解决方案的详细信息吗?我仍在努力为此考虑递归关系。我不知道一个点左侧的面积如何用于计算下一个点的面积。
    • 我已经扩展了我的答案以尝试添加更多细节。
    【解决方案2】:

    我的答案和另一个很相似:

    我建议的算法是开始让 K=N,所有数字排序,并不断删除数字,直到达到所需的 K。您在每一步中选择删除的数字是代表最低损失的数字。

    示例:假设您有数字:

    3、7、9、13 和 19

    问题是K=3

    你从 K​​=5 开始(所有数字都被选中)。

    3 + 7 + 9 + 13 + 19 = 51

    要删除的第一个数字:

    如果选择 3: 0 + 7 + 9 + 13 + 19 = 48(我们输了 3)

    如果选择 4:(7 变为 3) 3 + 3 + 9 + 13 + 19 = 47(我们输了 4)

    如果选择 9:(9 变为 7) 3 + 7 + 7 + 13 + 19 = 49(我们输了 2)

    如果选择 13:我们输掉 13 - 9 = 4

    如果选择 19:我们输掉 19 - 13 = 6

    这种情况下的最低损失是:数字 9(损失=2)。

    我们删除 9,然后我们有 K=4。

    对于要删除的第二个数字,我们有 4 个选项:

    如果我们删除 3: 0 + 7 + 7 + 13 + 19 = #(我们输了 3)

    如果我们去掉 7,所有的 7 都会变成 3: 3 + 3 + 3 + 13 + 19 = #(我们失去了两个 7 变成 3 = (7-3) x 2 = 8)

    如果我们删除 13: 3 + 7 + 7 + 7 + 19(损失 = 13 - 7 = 6)

    如果 19 被删除: 3 + 7 + 7 + 13 + 13(损失 = 6)

    这里最好的选择是删除#3 然后 K=3 达到总和:46

    我不知道这是否是最佳的,您可以通过比较与蛮力多种情况进行比较来验证。但是,即使这不是最佳的,它也可以产生良好的结果。

    【讨论】:

    • 这似乎是一个贪婪的解决方案。很有意思!我会试试这个,谢谢!
    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多