1

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

前任。说我有变量

n = 100

和一组数字

t = {86, 23, 19, 8, 42, 12, 49}

给定这个列表,最接近 n 的 4 组合是 49 + 23 + 19 + 8 = 99。

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

4

2 回答 2

2

这看起来像是“子集总和”(参见:http ://en.wikipedia.org/wiki/Subset_sum_problem )问题的一个变体,已知它是 NP 完全的,所以很遗憾很可能不会有任何聪明的算法无论如何,在最坏的情况下,它的运行速度会比项目数量的指数更快。

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

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

于 2013-03-26T19:37:15.593 回答
0

假设所有数字都是正整数,可以按照 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
于 2013-03-26T20:46:38.420 回答