具有固定总和的行的Matlab矩阵

时间:2015-12-09 00:11:22

标签: matlab matrix

我正在尝试在Matlab中构建一个矩阵,其中行的总和是不变的,但每个组合都被考虑在内。

例如,取一个NxM matrix,其中M是固定数字,N取决于K,所有行必须求和的结果。 例如,说K = 3M = 3,这将给出矩阵:

[1,1,1
2,1,0
2,0,1
1,2,0
1,0,2
0,2,1
0,1,2
3,0,0
0,3,0
0,0,3]

目前,我首先创建所有可能组合的矩阵,而不考虑总和(例如,这也包含[2,2,1]和[3,3,3])然后扔掉和不等于K

的元素

然而,这是非常低效的内存(特别是对于较大的KM),但我没想到在没有首先构造总矩阵的情况下构造这个矩阵的好方法。

这可能是一个很好的方式吗?或者我应该使用一大堆for循环?

2 个答案:

答案 0 :(得分:3)

这是一个使用动态编程的非常简单的版本。动态编程的基本思想是建立一个数据结构(这里是S),它保存同一问题的较小实例的中间结果。

M=3;
K=3;
%S(k+1,m) will hold the intermediate result for k and m
S=cell(K+1,M);
%Initialisation, for M=1 there is only a trivial solution using one number.
S(:,1)=num2cell(0:K);
for iM=2:M
    for temporary_k=0:K
        for new_element=0:temporary_k
            h=S{temporary_k-new_element+1,iM-1};
            h(:,end+1)=new_element;
            S{temporary_k+1,iM}=[S{temporary_k+1,iM};h];
        end        
    end
end
final_result=S{K+1,M}

答案 1 :(得分:1)

这可能比原始方法更有效,尽管它仍会生成(然后丢弃)比所需更多的行。

M表示列数,S表示所需的总和。该问题可以解释为将长度为S的区间划分为具有非负整数长度的M子区间

想法是生成而不是子区间长度,但是子区间边;从那些计算子区间长度。这可以通过以下步骤完成:

  1. M-10之间的子区间边是S个整数值(不一定不同)。这些可以使用例如Cartesian product生成为this answer

  2. 对间隔边进行排序,并删除重复的边集。这就是为什么算法不是完全有效的原因:它产生重复。但希望丢弃的暂定解决方案的数量将少于原始方法,因为这确实考虑了固定金额。

  3. 从边缘计算子区间长度。每个长度是两个连续边之间的差异,包括0处的固定初始边缘和S处的最终边缘。

  4. 代码:

    %// Data
    S = 3; %// desired sum
    M = 3; %// number of pieces
    
    %// Step 1 (adapted from linked answer):
    combs = cell(1,M-1);
    [combs{end:-1:1}] = ndgrid(0:S);
    combs = cat(M+1, combs{:});
    combs = reshape(combs,[],M-1);
    
    %// Step 2
    combs = unique(sort(combs,2), 'rows');
    
    %// Step 3
    combs = [zeros(size(combs,1),1) combs repmat(S, size(combs,1),1)]
    result = diff(combs,[],2);
    

    结果以lexicographical order排序。在您的示例中,

    result =
         0     0     3
         0     1     2
         0     2     1
         0     3     0
         1     0     2
         1     1     1
         1     2     0
         2     0     1
         2     1     0
         3     0     0