排列一组数字以适应特定大小总计

时间:2012-06-08 14:19:40

标签: excel matlab octave combinatorics libreoffice

我在一个大小不等的小组中有几个不同的数字,并希望根据小组的最大大小来计算这些数字应该进入的组。

数字示例:10,20,30,40,50,60

条件示例:数字可以在组中累加的最大总数 是60

所以从上面的例子来看,答案是:

第1组的数字为10,20,30

第2组的数字为40

第3组的数字为50

第4组的数字为60

在matlab / octave或excel / librecalc中是否可以计算出这种方法?

PS:一个组也可以有40和20,组总数不能超过60.但他们只能使用每个数字一次。

是否有用于此的数学术语?

1 个答案:

答案 0 :(得分:1)

编辑:

下面的解决方案使用强力方法生成powersets幂集(虽然已修剪)。然后检查满足条件集的组(即将所有数字分成组,使得任何组都不包含超过60的总和)。我从PMTK3工具箱中的powerset.m函数借用了一些代码。

对于像这样的小问题,这应该可以正常工作,但我怀疑它会在规模上以指数级增长以获得更大的输入。我确信那里有更好的启发式/算法,所以以此为出发点......

%# set of numbers
S = [10,20,30,40,50,60];

%# powerset of S (exclude empty set)
b = (dec2bin(2^numel(S)-1:-1:1) == '1');
P = cellfun(@(idx)S(idx), num2cell(b,2), 'UniformOutput',false);

%# keep only sets where the sum is at most 60
P = P(cellfun(@sum,P) <= 60);

%# take the powerset of the powerset, although we can
%# reduce it to no more than numel(S) subsets in each.
%# The idea here is: nchoosek(p,1:numel(s))
b = (dec2bin(2^numel(P)-1:-1:1) == '1');
b = b(sum(b,2)<=numel(S),:);
PP = cellfun(@(idx)P(idx), num2cell(b,2), 'UniformOutput',false);

%# condition: every number appears exactly once in groups
ppp = cellfun(@(x) [x{:}], PP, 'UniformOutput',false);
idx = find(cellfun(@numel,ppp) == numel(S));
idx2 = ismember(sort(cell2mat(ppp(idx)),2), S, 'rows');
PP = PP( idx(idx2) );

%# cleanup, and show result
clearvars -except S PP
celldisp(PP)

这给了我12个解决方案。例如:

>> PP{1}{:}
ans =
    10    20    30
ans =
    40
ans =
    50
ans =
    60

>> PP{6}{:}
ans =
    10    40
ans =
    20
ans =
    30
ans =
    50
ans =
    60

>> PP{12}{:}
ans =
    10
ans =
    20
ans =
    30
ans =
    40
ans =
    50
ans =
    60
相关问题