【问题标题】:Algorithm to select Player with max points but with a given cost [closed]选择具有最大积分但具有给定成本的玩家的算法[关闭]
【发布时间】:2012-10-31 09:39:16
【问题描述】:

我需要一个执行以下操作的算法:

在一个 NBA 梦幻联赛中,给定:

  1. 每个玩家的平均总分
  2. 每个玩家的价格
  3. 工资帽

选择最佳的 9 人阵容。

举个简单的例子,假设联盟中只有四名球员,你有 10,000 美元的工资帽,并且你想要最佳(即最高分)三人阵容。以下是平均积分和价格:

勒布朗詹姆斯:30分/场; 5,000 美元
科比·布莱恩特:25分/场; $3,500
德隆-威廉姆斯:20分/场; 2,500 美元
Shelvin Mack:15分/场; 2,000 美元

最佳阵容是科比、威廉姆斯和麦克,这将花费 8,000 美元并获得 60 分。

还有一个进一步的限制:程序必须为每个位置选择一定数量的球员(例如,两名控球后卫、两名得分后卫、两名小前锋、两名大前锋和一名中锋)。这就是让程序设计变得困难的原因。

【问题讨论】:

  • 没有最后一个约束,问题可以很容易地简化为knapsack problem,它有一个伪多项式时间解。
  • 詹姆斯、威廉姆斯、麦克肯定更好 - 9500 美元,65 分?
  • 每个玩家只能打一个位置,对吧?

标签: algorithm data-structures


【解决方案1】:

首先,很容易看出问题的泛化是NP-Hard,并且可以从Knapsack Problem瞬间归约:

给定一个背包问题:weight=W, costs_of_items=C, weight_of_items=X,将问题简化为这个问题,不限制玩家数量(泛化最多为k玩家,其中k由你选择)。

因此,我们可以得出结论,该问题没有已知的多项式时间解。

但是,我们可以开发基于knapsack pseudo-polynomial solution 的解决方案。
为简单起见,假设我们只对小前锋的数量进行了限制(可以应用答案的原则来添加更多限制)。

那么,问题可以通过以下递归方式解决:

if i is not a forward, same as the original knapsack, while maintaining the #forwards
    f(i,points,forwards) = max {
                f(i-1,points-C[i],forwards)
                f(i-1,points,forwards)
                           }
if i is a forward:
    f(i,points,forwards) = max {
                //We used one of the forwards if we add this forward to the team
                f(i-1,points-C[i],forwards-1) 
                f(i-1,points,forwards)
                           }

其中一个维度为零时,基数将全为零:f(0,_,_)=f(_,0,_)=0(与普通背包相同)和f(_,_,-1)=-infnity(无效解决方案)

答案将是f(2,W,n)(转发次数为2,如果不同,也应更改)。 W 是工资帽,n 是球员人数。

DP 解将自下而上填充表示递归的矩阵以获得伪多项式时间解(仅当限制条件不变时才为伪多项式)。

通过重复这个过程,并为每个标准添加一个维度,这个问题将通过 DP 解决方案得到最佳解决。

您将获得的复杂性是O(B^p * W * n) - 其中:
B 是“分支因素” - 在您的情况下,每个位置的玩家人数+1(为零)B=3
W = 工资帽
n = 可供选择的玩家数量


如果您发现最优解太耗时,我建议您选择启发式解决方案,例如hill climbingGenetic Algorithms,它们会尽量优化结果可以,但不能保证找到全局最大值。

【讨论】:

    【解决方案2】:

    使用动态规划可以轻松解决这个问题。参考this

    f[i][j] 成为我们在第一个i 玩家使用j 美元可以获得的最高分,所以

    f[i][j] = 最大值{

    1. f[i - 1][j] //我们不选择第i个玩家
    2. f[i - 1][j - cost[i]] + point[i] //我们选择他

    }

    最后f[TOTALPLAYER][MONEYCAP] 是答案。

    主要思想是决定是否为每个玩家选择他。

    数组f[][] 只是用来加速搜索过程。

    顺便说一句,Chowlett 是对的。

    【讨论】:

    • 它没有解决:“前 9 名球员”和“2 of... 2 of...”,算法产生的答案可能是 15 便宜,所有前锋球员,而不是 9满足限制的膨胀的。我清楚地指出了与背包问题的相似之处,并且经典的解决方案不足以作为对该问题的评论。
    • 这是问题的本质,一旦你理解了这一点,调整它来满足其他要求就不难了。
    • 我也想要完全相同的脚本。如果有请提供给我。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 2014-06-15
    • 2022-10-05
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多