Matrix 快速高效地创建二进制矩阵

Matrix 快速高效地创建二进制矩阵,matrix,permutation,combinations,combinatorics,sparse-matrix,Matrix,Permutation,Combinations,Combinatorics,Sparse Matrix,当我试图解决一个比我想象的更难的问题时,我遇到了麻烦。给定一个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语言中的递归算法,但是我不太确定它是否正确,因为它显然在最长的时间内没有工作

当我试图解决一个比我想象的更难的问题时,我遇到了麻烦。给定一个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语言中的递归算法,但是我不太确定它是否正确,因为它显然在最长的时间内没有工作,缺少了一些组合。在改变递归之后,至少组合的数量是正确的,对于nxm,我可以手动检查它似乎是正确的

但是:从一开始,内存消耗就很糟糕

1 1
0 0
0 0
和最右边的列,将1设置为0,并将下面一行中的0设置为1(如果有行)。然后我向左移动一列(重置我对最右边的列所做的操作,比如考虑进位)并迭代1的位置,对于每次迭代,我再次向右递归,直到没有列剩下来迭代它的1。这种方法对您来说可能有些尴尬(代码对我来说是这样),但我认为它就像在polyad系统中计数一样,其中列是数字,1的位置给出了数字的值

也许这只是我的一种不好的递归方式,但目前我必须为每次递归复制当前数组,这当然很糟糕,但这是我找到的唯一一种方法

0 1
1 0
0 0
并复制两次以生成

0 0
1 1
0 0

彼此独立比较容易。但是在C中释放内存的同时递归似乎不符合我的经验水平。我已经用Java进行了重写,希望GC能帮我解决这个问题(我不敢相信,但看起来确实是这样),但是在这里,分析表明,复制数据消耗了99%的周期

你对我的问题有什么建议吗?有没有一个名字,更不用说现有的算法了?你手头有递归的伪代码吗?非常感谢吸烟的大脑


我甚至不确定这是一个组合问题还是置换问题

好的,从我对你的问题的评论中说出我的想法,我认为你的问题可以归结为一些非常简单的迭代,基本上不需要任何内存:

通过了解您所做的只是简单的计数,我们可以设计一种迭代方法。如果你有一个2x3矩阵,它相当于一个三元数系统中的两位数的计数。这意味着我们可以表示的最大值是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的所有数字进行打印,您就拥有了所有的解决方案

这非常简单,没有任何“聪明”的数学技巧

首先,对于非零项,一种表示稀疏矩阵的标准方法称为:(index_行、index_列、值)

其次,您的设置非常基本:您的值都是1。[因此,您只需要存储(ix_行,ix_列)。]

第三:变得更简单:每列只有一行。因此,对于给定的矩阵,大小为nxp(行x列),我们可以假设有P个条目。让我们假设给定矩阵的坐标列表中,索引_列条目的值为1:P,所有条目的值均为1。[即,“完整”坐标表将是:(九行(1)、1、1)、(九行(2)、2、1),…,(九行(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),然后一次移动一步


这将生成所有必要的坐标列表来描述所有矩阵。

也许我已经回答了您的问题,但是处理1所在的行不是更容易,而不是传递整个矩阵,然后根据该矩阵打印输出吗,我的直觉告诉我递归不是一种方法——子问题根本不依赖于前面的结果,反之亦然,问题是基本的迭代,正如你正确地观察到的,它相当于在一个有N个数字的M元数系统中计数:这是迭代!添加了标签[sparse matrix],因为这就是这个过程所创建的。好的,我已经解决了这个问题,但是用了一种完全不同的方式,尽管使用了稀疏矩阵。但我通过计算二进制数来创建它们,我知道有多少个组合,从一个零数组开始,我在循环中加1。搬运操作很容易在一段时间内完成。谢谢,但我仍然不确定我是否得到了它,这是我真正需要的。在我看来,在移到(左边)之后,右边的所有元素都将被固定为N,失去了很多可能性。还是我弄错了?嗯,也许你的意思是有(1,1,…,1)的P(?)向量?它不是固定在N:你重新开始。例如,对于N=3,P=2:(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)。这很像二进制或十进制计数(比如里程表),可以在P深度递归中实现。递归内存是否有效,因为我递归的单个向量就足够了?我想用N和pw的值进行实验
0 0
1 0
0 1