找到与特定数字相近的数字组合

时间:2015-10-15 12:54:03

标签: algorithm matlab combinatorics heuristics

我有一个向量#secondary { /* left Sidebar */ width: 18rem; margin-left: -67rem; float: left; position: relative; } #tertiary { /* right Sidebar */ width: 18rem; margin-right: -23rem; float: right; position: relative; } ,即

A

我试图找到一组由此向量A = [300; 165; 150; 150; 400; 300; 80; 250; 165; 80; 200] 的元素组成的向量,以便它们的元素总和尽可能接近400的值,以便向量{{的所有元素1}}包含在不相交的向量集中。

例如,400已经是400,所以这是第一组没有松弛的向量。

另一组是A的向量,它们的总和是400.

另外两个可以是两组向量A,它们的总和是380,所以20的松弛就会受到影响。

另一个是[250 150],他们总计330,松弛70.最后一个是200和150,松弛50。总松弛是20 + 20 + 70 + 50 = 160。

我正在尝试找到一种可以最大限度地减少松弛的启发式或算法(不是编程模型)。我在Matlab编码。

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

v = [300; 165; 150; 150; 400; 300; 80; 250; 165; 80; 200];
binarystr = dec2bin(1:(2^(length(v))-1));
bincell = mat2cell(binarystr,ones(size(binarystr ,1),1),ones(size(binarystr ,2),1));
bin = cellfun(@(x) str2double(x),bincell);

现在您可以乘以找到所有组合:

comb = b*v;

找到最低

target = 400;
[val,index] = min(abs(comb-target));

如果你想知道组合是什么,你可以寻找索引:

idxs = find(bin(index,:));

,值为:

disp(idxs)
disp(v(idxs))

希望这有帮助。

答案 1 :(得分:0)

所以我认为这是一个非常有趣的问题,并在工作中开始(我希望我的老板不会发现),但我错过了一部分。代码非常可怕,但我想展示我猜的概念。

A = [300; 165; 150; 150; 400; 300; 80; 250; 165; 80; 200] ;

P = (1 - (sum(A) /400 - floor(sum(A)/400))) * 400; %//minimum slack to be achieved

%//Round 1 G1 = zeros(floor(sum(A)/400)+1,3) for t = 1:floor(sum(A)/400)+1 if size(A,1) > 1 %//single combination [F indF] = min(abs(A-400)); %//double combination if size(A >1) D = combntns(A,2); sumD = sum(D,2); [F2 indF2] = min(abs(sumD-400)); end %//triple combination if size(A >2) T = combntns(A,3); sumT = sum(T,2); [F3 indF3] = min(abs(sumT-400)); end %remove 1 [R removeInd] = min([F,F2,F3]); if removeInd == 1 G1(t,1) = A(indF); A(indF) =[]; else if removeInd ==2 G1(t,1:2) = D(indF2,:) ; [tmp,tmp2] = intersect(A,G1(t,:)); A(tmp2) = []; else removeInd == 3 G1(t,:) = T(indF3,:) ; [tmp,tmp2] = intersect(A,G1(t,:)); A(tmp2) = [] ; end end

else if size(A,1) == 1 G1(t,1) = A; end end

end

    </pre></code>

the results:

>>400   0   0
  150   250 0
  165   150 80
  300   80  0
  165   200 0
  300   0   0

The reason the results were wrong is because I searched for subsets with length of 1,2 and 3. 4 is not possible, since it produce huge results (but you can include it anyways). If I switch to subsets with length of 1 and 2 I get the right answer. So I think the step I am missing is how long my subsets can be.

results when max length of subset is set to 2:

>>400 0 0 150 250 0 300 80 0 300 80 0 165 200 0 165 150 0

你要做的只是三重组合%,并改变这一行:[R removeInd] = min([F,F2]);没有F3