Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 最大化整数子集的网络算法_Algorithm_Networking_Dynamic Programming - Fatal编程技术网

Algorithm 最大化整数子集的网络算法

Algorithm 最大化整数子集的网络算法,algorithm,networking,dynamic-programming,Algorithm,Networking,Dynamic Programming,我目前正在从事一个pet项目,该项目模拟了两种不同类型的网络。其中一个需要一些特定的条件,直到现在我都是蛮力强迫的。然而,它的伸缩性不好,所以我试图有效地做到这一点,但这个算法真的难住了我!我将尽可能笼统地描述这个问题 给定一组整数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 我的直觉是,这个解决方案是一个动态规划算法,但我

我目前正在从事一个pet项目,该项目模拟了两种不同类型的网络。其中一个需要一些特定的条件,直到现在我都是蛮力强迫的。然而,它的伸缩性不好,所以我试图有效地做到这一点,但这个算法真的难住了我!我将尽可能笼统地描述这个问题

给定一组整数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


我的直觉是,这个解决方案是一个动态规划算法,但我可能会偏离这个方向。任何帮助都将不胜感激

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

对数字集进行排序并绘制一条曲线,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),这样你就不必回顾前面的一点了。如果你能做到这一点,你可以节省存储时间,只需存储几个中间点,并在较小的部分上重新解决问题,以回溯过去,但你需要极度缺乏存储空间才能使之有价值。

我的答案与另一个答案非常相似:

我建议的算法是从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)x2=8)

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

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

这里的最佳选择是删除#3 然后K=3,求和为46


我不知道这是否是最优的,你可以通过比较与暴力的多个案例来验证。但是,即使这不是最优的,它也能给出很好的结果。

这显然是同样的问题,谢谢!对这个的视觉解释真的很酷。我有一个关于解决办法的问题。我们需要一个包含nk个元素的表,还是只需要一个包含n个元素的数组?“最右边的一点”似乎意味着