Performance 降低了算法的时间复杂度

Performance 降低了算法的时间复杂度,performance,algorithm,time-complexity,Performance,Algorithm,Time Complexity,我在玩一个有武器锻造组件的游戏,你把两种武器结合起来,得到一种新的。武器组合的数量之多(参见第页的“6.1.刀片组合表”)使得我们很难通过反复锻造从现有武器中最终创造出什么,所以我试着编写一个程序来为我做到这一点。我给它一份我目前拥有的武器清单,例如: 方济各 塔巴津 克里斯 它给了我一张我能锻造的所有武器的清单: 球锤 查姆卡克 德克 方济各 大新月 飞刀 问题是我使用的是一种暴力算法,它的伸缩性非常差;计算七种起始武器的所有可能武器大约需要15秒,计算八种起始武器需要几分钟。我希望它

我在玩一个有武器锻造组件的游戏,你把两种武器结合起来,得到一种新的。武器组合的数量之多(参见第页的“6.1.刀片组合表”)使得我们很难通过反复锻造从现有武器中最终创造出什么,所以我试着编写一个程序来为我做到这一点。我给它一份我目前拥有的武器清单,例如:

  • 方济各
  • 塔巴津
  • 克里斯
它给了我一张我能锻造的所有武器的清单:

  • 球锤
  • 查姆卡克
  • 德克
  • 方济各
  • 大新月
  • 飞刀
问题是我使用的是一种暴力算法,它的伸缩性非常差;计算七种起始武器的所有可能武器大约需要15秒,计算八种起始武器需要几分钟。我希望它能够计算出多达64件武器(你一次最多可以持有64件武器),但我认为我活不长,看不到结果

function find_possible_weapons(source_weapons)
{
    for (i in source_weapons)
    {
        for (j in source_weapons)
        {
            if (i != j)
            {
                result_weapon = combine_weapons(source_weapons[i], source_weapons[j]);

                new_weapons = array();
                new_weapons.add(result_weapon);
                for (k in source_weapons)
                {
                    if (k != i && k != j)
                        new_weapons.add(source_weapons[k]);
                }
                find_possible_weapons(new_weapons);
            }
        }
    }
}
中文:我从我的源武器列表中尝试两种武器的每一种组合。对于这些组合中的每一种,我都会创建一个新的列表,列出我在该组合之后拥有的所有武器(也就是说,新组合的武器加上除我组合的两种武器之外的所有源武器),然后对新列表重复这些步骤

有更好的方法吗

请注意,按相反顺序组合武器可能会改变结果(剑+剑=短剑,但剑+剑=斯帕塔),因此我不能跳过
j
循环中的这些反转

编辑:下面是我上面给出的测试示例的分解图,以显示算法的作用。括号中的一行显示组合的结果,下一行是由此创建的新武器列表:

francisca,tabarzin,kris
[francisca + tabarzin = chamkaq]
    chamkaq,kris
    [chamkaq + kris = large crescent]
        large crescent
    [kris + chamkaq = large crescent]
        large crescent
[francisca + kris = dirk]
    dirk,tabarzin
    [dirk + tabarzin = francisca]
        francisca
    [tabarzin + dirk = francisca]
        francisca
[tabarzin + francisca = chamkaq]
    chamkaq,kris
    [chamkaq + kris = large crescent]
        large crescent
    [kris + chamkaq = large crescent]
        large crescent
[tabarzin + kris = throwing knife]
    throwing knife,francisca
    [throwing knife + francisca = ball mace]
        ball mace
    [francisca + throwing knife = ball mace]
        ball mace
[kris + francisca = dirk]
    dirk,tabarzin
    [dirk + tabarzin = francisca]
        francisca
    [tabarzin + dirk = francisca]
        francisca
[kris + tabarzin = throwing knife]
    throwing knife,francisca
    [throwing knife + francisca = ball mace]
        ball mace
    [francisca + throwing knife = ball mace]
        ball mace
此外,请注意,武器清单中的重复项目非常重要,无法删除。例如,如果我在我的起始武器列表中添加第二个KRI,那么我有以下列表:

  • 方济各
  • 塔巴津
  • 克里斯
  • 克里斯
然后我就可以锻造以下物品:

  • 球锤
  • 战斧
  • 战刀
  • 查姆卡克
  • 德克
  • 方济各
  • 克里斯
  • 库迪
  • 大新月
  • 斯克拉马萨克斯
  • 飞刀
添加了一个重复的kris,使我能够打造出四件我以前无法打造的新物品。它还将四项清单的锻造试验总数从三项清单的27项增加到252项


编辑:我觉得解决这个问题需要比我更多的数学和计算机科学知识,所以我打算放弃。起初,这似乎是一个足够简单的问题,但后来,旅行推销员也是如此。我接受David Eisenstat的回答,因为记忆和跳过重复项目列表的建议在执行时间上产生了巨大的差异,并且似乎适用于许多类似的问题。

您可能希望从创建武器[][]矩阵开始,以显示锻造每一对的结果。您可以将武器的名称映射到矩阵轴的索引,并在固定时间内查找武器组合的结果。

这不是一个巨大的节省,但是查看源文档,有时组合武器会产生与组合武器相同的武器。我想你不会想这样做,因为你最终会拥有更少的武器

因此,如果您添加了一个检查结果武器是否与其中一个输入的类型相同的检查,并且没有继续递归调用find_-apability_-武器(new_-arms),那么您应该稍微减少搜索

我能想到的另一件事是,你没有记录完成的工作,因此如果从find_Obably_武器(新武器)返回的武器与你通过组合其他武器已经获得的武器相同,那么你可能会多次执行相同的搜索分支

e、 如果你有a,b,c,d,e,f,g,如果a+b=x,c+d=x,那么你的算法将执行两次比较x和e,f,g。所以,如果你对你已经计算过的内容进行跟踪,你将成为赢家

基本上,你必须修剪搜索树。有很多不同的技术可以做到这一点:。如果你想要更多的建议,我建议你去计算机科学堆栈交换


如果您仍在苦苦挣扎,那么您可以开始对项目/结果项目进行加权,只关注“高增益”对象的计算…

我认为您不太可能对这个问题获得一个好的总体答案,因为 如果有一个有效的算法来解决你的问题,那么它也能解决NP完全问题

例如,考虑在二进制矩阵中求独立行的最大数的问题。 这是一个已知的NP完全问题(例如,通过显示与的等价性)

我们可以通过以下方式将此问题简化为您的问题:

我们可以开始为二进制矩阵中的每一列持有一件武器,然后我们想象每一行都描述了一种制造新武器的替代方法(比如战斧)。 我们构造武器转换表,以便使用方法i制作战斧,我们需要所有武器j,使得M[i,j]等于1(这可能涉及发明一些额外的武器)

然后我们建造了一系列超级武器,这些武器可以通过组合不同数量的战斗轴来制造

例如,超级终极战斧可能需要组合4个战斧

如果我们能够从你的起始武器中找出最好的武器,那么我们已经解决了p
minimize sum_{i, j => k} x_{ijk} (to prevent wasteful cycles)
for all i:   sum_{j, k: j + k => i} x_{jki}
           - sum_{j, k: j + i => k} x_{jik}
           - sum_{j, k: i + j => k} x_{ijk} >= q_i,
for all i + j => k: x_{ijk} >= 0,