Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 数的子集之和_Algorithm_Math_Lua_Knapsack Problem - Fatal编程技术网

Algorithm 数的子集之和

Algorithm 数的子集之和,algorithm,math,lua,knapsack-problem,Algorithm,Math,Lua,Knapsack Problem,假设我有一个数字'n'和一个数字表。我想在表中选择最多四个数字,这四个数字的总和将是与n最接近的匹配。给定表的长度“L”,它必须经过的组合数为(6*L+11*L^2+6*L^3+L^4)/24 假设我有这个变量 n = 100 还有一组数字 t = {86, 23, 19, 8, 42, 12, 49} 在这个列表中,4到n的最接近组合是49+23+19+8=99 用尽可能少的计算次数来实现这一点的最佳方法是什么?这看起来像是已知的NP完全问题的“子集和”(见:)的一个变体,所以不幸的是,很

假设我有一个数字'n'和一个数字表。我想在表中选择最多四个数字,这四个数字的总和将是与n最接近的匹配。给定表的长度“L”,它必须经过的组合数为(6*L+11*L^2+6*L^3+L^4)/24

假设我有这个变量

n = 100
还有一组数字

t = {86, 23, 19, 8, 42, 12, 49}
在这个列表中,4到n的最接近组合是49+23+19+8=99


用尽可能少的计算次数来实现这一点的最佳方法是什么?

这看起来像是已知的NP完全问题的“子集和”(见:)的一个变体,所以不幸的是,很可能根本就没有任何聪明的算法,在最坏的情况下,它的运行速度会比项目数的指数更快

如果要检查的项目不多(大约10个),您可以尝试深度优先搜索,尽快修剪分支


如果有更多的项目需要检查,而不是搜索最佳解决方案,您最好尝试找到一个更好的近似值。

假设所有数字都是正整数,可以按照Yexo指出的方法进行:

local n = 100
local t = {86, 23, 19, 8, 42, 12, 49}
local max_terms = 4
-- best[subset_size][terms][k] = {abs_diff, expr}
local best = {[0] = {}}
for k = 1, n do best[0][k] = {k, ''} end
for terms = 0, max_terms do best[terms] = best[0] end
for subset_size = 1, #t do
   local new_best = {}
   for terms = subset_size == #t and max_terms or 0, max_terms do
      new_best[terms] = {}
      for k = subset_size == #t and n or 1, n do
         local b0 = best[terms][k]
         local diff = k - t[subset_size]
         local b1 = terms > 0 and (
            diff > 0 and {
               best[terms-1][diff][1],
               best[terms-1][diff][2]..'+'..t[subset_size]
            } or {math.abs(diff), t[subset_size]}
         ) or b0
         new_best[terms][k] = b1[1] < b0[1] and b1 or b0
      end
   end
   best = new_best
end
local expr = best[max_terms][n][2]:match'^%+?(.*)'
print((loadstring or load)('return '..expr)()..' = '..expr)

-- Output
99 = 23+19+8+49
local n=100
局部t={86,23,19,8,42,12,49}
局部最大项=4
--最佳[subset_size][terms][k]={abs_diff,expr}
局部最佳={[0]={}
对于k=1,n最好[0][k]={k',}结束
对于terms=0,max_terms做得最好[terms]=best[0]结束
对于子集_size=1,#t do
本地新_最佳={}
对于terms=subset_size==#t和max_terms或0,max_terms会
新的_最佳[术语]={}
对于k=subset_size==#t和n或1,n do
本地b0=最佳[术语][k]
局部差异=k-t[子集大小]
本地b1=术语>0和(
差值>0和{
最佳[条款-1][diff][1],
最佳[terms-1][diff][2]…'+'..t[子集大小]
}或者{math.abs(diff),t[subset_size]}
)或b0
新的[k]=b1[1]