Sum of a subset of numbers

╄→гoц情女王★ 提交于 2019-12-24 08:58:20

问题


Say I have one number 'n' and a table of numbers. I want to choose up to four of the numbers in the table, and the sum of those four will be the closest possible match to n. Given length 'L' of the table, the number of combinations it has to go through is (6*L + 11*L^2 + 6*L^3 + L^4)/24.

ex. Say I have the variable

n = 100

and the set of numbers

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

Given this list, the closest combination of four to n is 49 + 23 + 19 + 8 = 99.

What is the optimal way of doing this with the least possible number of calculations?


回答1:


This looks like a variation of the 'subset sum' (see: http://en.wikipedia.org/wiki/Subset_sum_problem) problem which is known to to be NP complete, so unfortunately most probably there won't be any clever algorithm at all that in the worst-case will run any faster that exponential in the number of items.

In case there are not many items to check (something about 10 or so) you might try a depth first search pruning branches as soon as possible.

If there are a lot more items to check most probably instead of searching for the optimal solution you might better try to find a somewhat good approximation.




回答2:


Assuming all numbers are positive integers, it could be done as Yexo pointed out:

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


来源:https://stackoverflow.com/questions/15645682/sum-of-a-subset-of-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!