带有 2675 个数字列表的子集总和

Posted

技术标签:

【中文标题】带有 2675 个数字列表的子集总和【英文标题】:Subset Sum with a list of 2675 numbers 【发布时间】:2017-03-24 14:51:06 【问题描述】:

我正在寻找是否可以有效解决问题的是/否答案。我很确定以我们目前可用的计算技术状态是不可能的。我很高兴知道我错了。所以这里什么都没有。

我有一个2576 号码列表。我试图在列表中找到总计为44576.54 的数字组合。数字列表包含从 5 位(两位精度)到 8 位(两位精度)的数字。

非常感谢您的帮助!

【问题讨论】:

“介绍”+1。如果您想在合理的时间内找到所有组合,我会说不!但不确定。也许某处有一些巫术算法。 列表中有负数吗?如果不是,那么最多四个 5 位数字可以是和的一部分,并且根本不能使用 6/7/8 位数字。这大大减少了要检查的组合数量。请注意,以浮点数指定数字会导致问题 - 任何数字总和都不太可能完全等于 44576.54,即使这是数学上正确的结果。最好将所有内容乘以 100,并且只处理整数。 【参考方案1】:

你错了。经典的动态规划算法将在现代计算硬件上快速解决这个问题。

【讨论】:

即使是非正整数?你能详细说明吗? @大卫 @ishan 是的,即使是非正整数(尽管大多数实现都需要对数组进行不同的索引)。 谢谢@David,你能指导我找到一个 URL 或任何可以帮助我在合理时间内解决该问题的材料 @ishan en.wikipedia.org/wiki/Subset_sum_problem,在伪多项式时间算法下。【参考方案2】:

这是动态规划算法,并且已经在Emercoin 引擎中实现,用于选择最佳 UTXO 子集。 有关此解决方案,请参阅 source code 和 article。

该算法的共同思路如下:

你有一组不同长度的“棒”(长度是你的数值)。 您需要选择杆的子集,总长度为 4457654。

    让您创建标志线,总和 + 1 的长度,即 4457655。如果找到值“i”的总和子集,则 LINE[i] = 1,如果找到值“i”的子集,则为零没有找到。最初,整个数组都是零填充的,因为没有找到任何总和。

    标记 LINE[0] := 1;这意味着,0.00 美元的总和可以很容易地找到 - 这是空子集。

    而(LINE[4457654] == 0):

    从套装中获取下一根杆。 将此棒应用到阵列的末端。即,在 LINE[4457654] 处的杆末端,在 LINE[4457654 - 杆长度]处的杆开始。 将杆从阵列末端移动到开始,并且: 如果 LINE[杆开始] == 1,则 LINE[杆结束] := 1;

【讨论】:

【参考方案3】:

这个问题基本上有两种解决方案:

    动态编程:复杂度总和*n,所以在您的情况下,这将非常大,您的程序不会在几天内完成。

    回溯解决方案:复杂度 2^n,这意味着您的程序不会结束多年,这就是为什么它被称为 NP-Hard 问题

我已经研究子集和问题很长时间了,我有一个算法,我已经测试了 n=400,它在几秒钟内就给出了结果。 目前我正在撰写论文以使其发表。分享您的意见。我会让你知道它是什么子集,这也将帮助我验证我的算法是否能解决实际问题。

顺便说一句,你能告诉我为什么你需要得到子集和吗?你的用例是什么?

【讨论】:

以上是关于带有 2675 个数字列表的子集总和的主要内容,如果未能解决你的问题,请参考以下文章

计算具有给定总和的子集的有效方法

回溯 - 给定一组数字,找到总和等于 M 的所有子集(给定 M)

在python中查找列表的子集的总和

使用动态编程从 Python 上的子集总和问题中获取所有子集

将数字列表划分为2个相等总和列表的算法

给定一个目标总和和一组整数,找到与该目标相加的最接近的数字子集