【问题标题】:Best way to search/filter (potentially several billion) combinations of items from multiple lists or arrays从多个列表或数组中搜索/过滤(可能数十亿)项目组合的最佳方式
【发布时间】:2020-01-20 22:43:42
【问题描述】:

我正在尝试编写一个程序来优化游戏的设备配置。问题如下:

  1. 有六个不同的装备槽可供角色放置物品。这由代码中每个插槽的 6 个单独项目列表表示,其中包含玩家拥有的所有设备。

  2. 程序将为每个可能的设备组合计算角色的总统计数据(每个列表中的 1 个)。这些计算出来的统计数据可以通过特定统计数据的最小值/最大值进行过滤,然后也可以按特定统计数据进行排序,以查明角色的特定目标统计数据集。

  3. 程序应该能够执行这些查询而不会耗尽内存或花费数小时,当然,主要问题是筛选数十亿种可能的组合。

我不确定用于完成此任务的任何支持数据结构或搜索算法的名称是什么(以便对解决方案进行更多研究)。我提出了以下想法,但我不确定我是否走在正确的轨道上,或者是否有人可以为我指明更有效的方向。

我追求的想法是使用递归,其中每个列表(对于每个可能的设备插槽)都设置为树结构,每个渐进式列表充当最后一个的子级。例如:

Weapons List
|
-----Armor List
     |
     ------Helm List... etc

树的每一层都会保留一个字典,其中包含它可以采用的每个子路径,其中包含每个列表中 1 项的 ID,并逐步计算赋予角色的统计数据(简单地添加武器 + 盔甲 + 头盔的统计数据)遍历树等等......)

当应用了最小/最大过滤器的任何统计信息达到该统计信息的边界时(即,如果统计信息在到达树的底层之前超过最大值,它会从字典中删除该“路径”从被遍历中删除整个可能的结果)。

这里的主要目标是减少搜索算法可能遍历的树路径,并在树需要计算它们之前删除尽可能多的无效结果,以使搜索尽可能快并避免任何浪费循环。当基于“最大”过滤器删除项目时,这似乎非常简单,因为当逐步添加每个项目的统计数据时,我们可以快速判断一个统计数据何时超过了它的预期最大值——但是当涉及到基于最小总统计数据停止路径时,我无法理解如何预测和删除这些路径,这些路径最终不会超过第六项的最小值。

为了简化这个想法,可以这样想:

我有 3 个数字数组

[X][0][1][2]
[0] 5  3  2
[1] 1  0  8 
[2] 3  2  7
[3] 2  1  0

我想从 3 个数组(总和)中找到最小为 9 且最大为 11 的所有组合。 每个数组必须至少选择但不超过 1 个项目,并且这些选定值的总和就是要搜索的内容。这将需要能够扩展到搜索 6 多个数组,每个数组包含 40 多个值。上述方法是否正确或最好的方法是什么(主要使用c#)

【问题讨论】:

  • 好问题!您目前使用的是multi-dimensional array [x,y] 还是array of arrays [x][y]?后者通常要快得多,并且有一篇很棒的帖子 here 可以帮助您入门。
  • @PerpetualJ 虽然 C# 锯齿状数组比多维数组快,但速度差异是个位数的因素。 OP的问题是组合的。使用更快的数组实现不会节省足够的时间来解决这类问题。
  • 所以基本上你想从数组中识别所有有效的项目组合。如果您有 n 个数组,每个数组有 k 个项目,如果您使用 Brute-force search,最坏情况的复杂度是 O(n^k)。那篇文章有一些关于优化和替代方案的想法,包括您正在考虑减少搜索空间的想法。

标签: c# search optimization multidimensional-array data-structures


【解决方案1】:

您应该能够通过为每个插槽使用下限和上限来过滤掉很多项目:

var minimum = slots.Sum(slot => slot.Minimum);
var maximum = slots.Sum(slot => slot.Maximum);

foreach (var slot in slots)
{
    var maxAvailable = maximum - slot.Maximum;
    var minAvailable = minimum - slot.Minimum;
    var filtered = slot.Items
         // If we choose the strongest item in all the other slots and it's still below the minimum
        .Where(item => item.Value + maxAvailable >= request.MinimumValue)
        // If we choose the weakest item in all the other slots and its still above the maximum
        .Where(item => item.Value + minAvailable <= request.MaximumValue);
}

完成此操作后,您可以保证所有组合都高于请求的最小值,但是某些组合也可能高于请求的最大值,因此将其与您目前的逻辑结合起来,我认为您应该会获得最佳效果性能。

【讨论】:

    猜你喜欢
    • 2017-01-22
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 2020-05-02
    • 1970-01-01
    • 2014-12-19
    相关资源
    最近更新 更多