我目前正在开发一个模拟几种不同类型网络的宠物项目。其中一个需要一些特定的条件,直到现在我才刚刚强迫。然而,它不能很好地扩展,所以我试图有效地做到这一点,但这个算法真的让我很难受!我会尝试尽可能地描述问题。
给定一组整数X和整数k,找到X的子集Y,它最大化M对X中每个值的总和:
M(s)= Y中的最大值,使得它小于或等于s。
例如,对于{2,4,5}和k = 2,解是{2,4},其值为2 + 4 + 4 = 10,因为M(2)= 2,M(4)= 4,和M(5)= 5.
我的直觉是解决方案是一种动态编程算法,但我可能会离开。任何帮助将不胜感激!
答案 0 :(得分:0)
这是一个解决方案的动态程序问题 - 我不确定它是不是你的,因为我不确定你所写的内容的细节,但它可能是。
对数字集进行排序,并使用x轴绘制曲线,以排序顺序给出数字的偏移量,y轴给出数字。曲线下面会有一些区域。
您的点数有限,通常比该组成员的数量少。您可以使用这些点中的每一个来标记集合的一个点,从而标记曲线的一个点。
在曲线下绘制直方图。在每个标记点处,从该点向右行有一条线,因此线条完全在曲线下方。每条这样的线都延伸到下一个标记点的x值,此时有一条线向上到新的标记点。
然后挑战是选择要标记的点以最大化从标记点向右的水平线下面积。这是简单的动态编程。如果您可以选择最多k个标记点,那么在直方图的每个点处计算出您可以使用0,1,2,..k标记点(可能包括该点)覆盖该点左侧的大部分区域。你可以通过参考你已经为左边的点找出的答案来计算每个点的答案。最正确的答案是整个问题的答案。
要扩展这一点:假设您正在计算最大区域以偏移量10结束的最佳解决方案。对于每个值为0的k,考虑采用先前的最佳解决方案,结束于0,1,2,3 ...... 9并保持该点的高度,而不引入新的线。这个区域的总面积是到那个点为止的区域加上新的区域,它通过它在该点的任何高度获得的时间乘以返回该点的距离。还要考虑这样做,但在该点使用额外的标记点,因此总面积是最佳解决方案的区域,其中j-1点高达例如第7点加上从第10点到第7点的距离,从第7点到达第7点。通过考虑这两种可能性,您可以使用0,1,2,... k标记点在第10点找出最佳解。< / p>
我认为这些问题是相关的,因为对于每个点,标记与否,它对直方图的贡献取决于它上面的线的高度,这是最大标记点的高度不大于我们的点正在考虑此刻。
要做到这一点,你需要一个kn元素数组,在每个点使用最多k个标记点,使用最佳解决方案覆盖区域。使用此大小的额外数组来记录导致此最佳解决方案的决策也很方便,因此您可以追溯答案。这具有大约kn ^ 2的成本,因为在n个点中的每个点处,您需要计算k值,并且在您执行此操作时回顾所有先前的点。我怀疑你可以通过改变你在每个点存储的内容的定义来将其减少到像O(kn)这样的东西,这样你就不必再回顾过去的一点了。如果你能做到这一点,你可以节省时间,只需存储一些中间点并在较小的部分上再次解决问题以追溯,但你需要拼命缺少存储才能实现值得一试。
答案 1 :(得分:0)
我的答案与另一个非常相似:
我建议的算法是开始使用K = N,所有数字都已订购,并继续删除数字直到达到所需的K.您在每一步中选择删除的数字是代表最低损失的数字。< / p>
示例:假设您有数字:
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将成为3s: 3 + 3 + 3 + 13 + 19 =#(我们失去两个7s变成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
我不知道这是否是最佳的,你可以通过比较与暴力相比来验证多个案例。但是,即使这不是最佳的,也可以产生良好的效果。