Joh*_*sky 17 algorithm optimization set packing mathematical-optimization
我有一组整数M和一个目标和k.我想找到M的子集,当它们加在一起时最接近k而不会过去.
例如:
M = {1, 3, 5, 5, 14}
k = 12
answer = {1, 5, 5}
because 1 + 5 + 5 = 11 and there is no way to make 12.
Run Code Online (Sandbox Code Playgroud)
我有一个额外的约束,即子集最多可以包含4个元素.
在我的应用程序中,| M |的大小 可以很大(大约数千个元素).如果无法在合理的时间内找到最佳答案,我对至少给出"好"答案的解决方案感兴趣.
现在我通过生成10,000个随机子集并选择最接近的子集来解决这个问题,这个子集的效果比预期的要好但是很慢.我不确定这实际上有多远,但任何有关这方面的见解对我来说都很有趣.
das*_*ght 14
由于您可以选择的项目数量有限制,因此可以使用相当简单的算法来完成.
该算法在"世代"中产生可能的总和.一代中的每个元素由表示总和的数字组成,并且其中的N元组M用于构建该总和.
第零代是空的; 生成X+1是通过遍历生成X,并将元素添加M到该代的每个值,并记录它们的总和用于下一代X+1.
在计算总和之前,检查其N元组是否存在您要添加的数字的索引.如果它在那里,请跳过该号码.接下来,检查总和:如果总和中已经存在X+1,则忽略它; 否则,记录新的总和,以及新的N元组索引(追加你从一代中添加到N元组的数字的索引X).
以下是这对您的输入有用:
第0代:空的
第1代:
1 - {0}
3 - {1}
5 - {2}
14 - {4}
Run Code Online (Sandbox Code Playgroud)
第2代:
4 - {0, 1}
6 - {0, 2}
8 - {1, 2}
10 - {2, 3}
15 - {0, 4}
17 - {1, 4}
19 - {2, 4}
Run Code Online (Sandbox Code Playgroud)
第3代:
9 - {0, 1, 2}
11 - {0, 2, 3}
13 - {1, 2, 3}
18 - {0, 1, 4}
20 - {0, 2, 4}
22 - {1, 2, 4}
24 - {2, 3, 4}
Run Code Online (Sandbox Code Playgroud)
第4代:
14 - {0, 1, 2, 3}
23 - {0, 1, 2, 4}
25 - {0, 2, 3, 4}
27 - {1, 2, 3, 4}
Run Code Online (Sandbox Code Playgroud)
您现在可以在四代中搜索最接近目标编号的数字k.