是否可以将matrix A
行n
列和n
列分解为m [n x n]
置换矩阵的总和。其中m是matrix A
中每行和每列的1的数量?
更新
是的,这是可能的。我遇到了这样一个例子,如下所示 - 但我们怎样才能概括出答案呢?
答案 0 :(得分:0)
对于第一个排列矩阵,取第一行中的第一个。对于第二行,请获取您尚未拥有的列中的第一行。对于第三行,请获取您尚未拥有的列中的第一行。等等。对所有行执行此操作。
您现在有一个排列矩阵。
接下来从原始矩阵中减去第一个置换矩阵。现在,这个新矩阵在每行和每列中都有m-1
个。因此,请多次重复此过程m-1
,然后您将拥有m
个排列矩阵。
您可以跳过最后一步,因为每行和每列中一个1的矩阵已经是一个置换矩阵。没有必要进行任何计算。
这是一种贪婪的算法并不总是有效。我们可以通过稍微改变选择规则来使其工作。见下文:
对于你的例子:
1 0 1 1
A = 1 1 0 1
1 1 1 0
0 1 1 1
在第一步中,我们为第一行选择(1,1),为第二行选择(2,2),为第三行选择(3,3),为第四行选择(4,4)。然后我们有:
1 0 0 0 0 0 1 1
A = 0 1 0 0 + 1 0 0 1
0 0 1 0 1 1 0 0
0 0 0 1 0 1 1 0
第一个矩阵是置换矩阵。第二个矩阵在每行和每列中恰好有两个1。所以我们按顺序选择:(1,3),(2,1),(3,2)和...我们遇到了麻烦:第4列中包含1的行已经被使用过。
那么我们该如何解决这个问题呢?好吧,我们可以跟踪每列中剩余1的数量。我们选择剩余1的最小数量的列,而不是选择未使用的第一列。对于上面的第二个矩阵:
0 0 1 1 0 0 X 0 0 0 X 0 0 0 X 0
B = 1 0 0 1 --> 1 0 0 1 --> 0 0 0 X --> 0 0 0 X
1 1 0 0 1 1 0 0 1 1 0 0 X 0 0 0
0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0
------- ------- ------- -------
2 2 2 2 2 2 X 1 1 2 X X X 1 X X
因此,我们将在第二步中选择第4列,在第3步中选择第1列,在第4步中选择第2列。
始终只能有一列,其中一列剩余1.另一列必须已在前m-1
行中删除。如果你有两个这样的列,其中一个必须被选为之前的最小列。
答案 1 :(得分:0)
您想要的是1-factorization。一种算法反复找到完美匹配并将其删除;可能还有其他人。
答案 2 :(得分:0)
这可以使用递归(回溯或深度优先遍历)算法轻松完成。以下是其解决方案的伪代码:
void printPermutationMatrices(const int OrigMat[][], int permutMat[], int curRow, const int n){
//curPermutMatrix is 1-D array where value of ith element contains the value of column where 1 is placed in ith row
if(curRow == n){//Base case
//do stuff with permutMat[]
printPermutMat(permutMat);
return;
}
for(int col=0; col<n; col++){//try to place 1 in cur_row in each col if possible and go further to next row in recursion
if(origM[cur_row][col] == 1){
permutMat[cur_row] = col;//choose this col for cur_row
if there is no conflict to place a 1 in [cur_row, col] in permutMat[]
perform(origM, curPermutMat, curRow+1, n);
}
}
}
以下是如何从您的主要功能调用:
int[] permutMat = new int[n];
printPermutationMatrices(originalMatrix, permutMat, 0, n);