在尝试解决一个对我来说比我想象的更难的问题时,我面临着麻烦。给定NxM的二进制矩阵,我想在每个列只有一个“1”的约束下生成所有可能的解决方案。对于2x3,那将是:
1 1
0 0
0 0
1 0
0 1
0 0
1 0
0 0
0 1
0 1
1 0
0 0
0 0
1 1
0 0
0 0
1 0
0 1
0 1
0 0
1 0
0 0
0 1
1 0
0 0
0 0
1 1
经过一些麻烦,我在C工作中有一个递归算法,但我不太确定它是否正确,因为它显然不能工作最长时间,缺少一些组合。更改递归后,至少组合的数量是正确的,对于N x M,我可以手动检查它似乎是正确的。
但是:当我从
开始时,内存消耗很糟糕1 1
0 0
0 0
和最右边的列,如果有任何行,则将1设置为0,将下面一行中的0设置为1。然后我向左边的一列(重置我对最右边的列做了什么,比如考虑进位)并迭代1的位置,并且对于每次迭代,我再次向右递归,直到没有剩下的列进行迭代这种方法对你来说可能看起来很尴尬(代码对我来说),但我喜欢它在polyad系统中计数,其中列是数字,1的位置给出数字的值。
也许这只是我破碎的递归方式,但是目前我必须为每次递归复制当前数组,这当然是可怕的,但我发现的唯一方法就是如此。
0 1
1 0
0 0
并将其复制两次以生成
0 0
1 1
0 0
和
0 0
1 0
0 1
彼此独立更容易。但是在递归时释放C中的内存似乎不符合我的经验水平。我已经在Java中进行了重写,希望GC可以帮助我(不能相信它,但看起来确实如此)但是同样,分析说当然复制数据正在吃99%的周期。
您对我的问题有什么建议吗?甚至可能有一个名称,而不是考虑现有的算法?你有手头递归的伪代码吗?非常感谢吸烟的大脑!
我甚至不确定这是组合问题还是排列问题。
答案 0 :(得分:1)
好的,只是通过在评论中对我的问题进行语言表达,我认为你的问题可以归结为一些非常简单的迭代,基本上根本不会使用任何内存:
从了解您正在做的事情是简单的计算,我们可以设计一个迭代的方法。如果你有一个像2x3矩阵的例子,它相当于在2位数的三元数系统中计数。这意味着我们可以表示的最大值是3 ^ 2 - 1 = 8。
这意味着我们将从0到8进行计数。现在转换为三元组,就像你手动将数字写入二进制一样。比如7,有多少3 ^ 1? 2!因此,矩阵中最左边1的位置是第2行(从0开始索引)。从我们正在转换的数字中减去3x2 = 6,留下1.有多少3 ^ 0? 1!所以最右边一列中的1位于第1行。
由此我们有足够的信息来打印解决方案,并且通过对0到M ^ N - 1的所有数字执行此操作,您就拥有了所有解决方案!
答案 1 :(得分:1)
这很简单,没有任何“聪明”的数学技巧。
首先,表示稀疏矩阵的一种标准方法称为coordinate list :( index_row,index_column,value),用于非零项。
其次,你的设置很基本:你的值都是1. [所以,你只需要存储(ix_row,ix_col)。]
第三:它变得更容易:每列只有一行。因此,对于大小为N x P(行x列)的给定矩阵,我们可以假设存在P个条目。让我们假设给定矩阵的坐标列表对于index_column条目具有1:P,对于所有条目具有值= 1。 [即“完整”坐标列表将是:(ix_row(1),1,1),(ix_row(2),2,1),...,(ix_row(P),P,1)]。
因此,在填充坐标列表时,问题是创建所有可能的行索引,这些索引只是从1:N,P次,替换采样。对于坐标列表中的每一行,您有N个选项。矩阵的数量是N ^ P。
创建所有(1:N)x(1:N)x ... x(1:N)向量的列表非常简单:从(1,1,1,....,1)开始并在最后一个元素中计算到(1,1,1,...,N)并一次移动一步。
这将生成描述所有矩阵的所有必要坐标列表。