编辑:
根据您的评论,我重新阅读了原始问题,并意识到我完全错过了问题的重点。我将在此处发布(希望)更相关的答案,但人们应该随时撤销任何赞成票。我曾讨论过发布一个新答案并删除这个答案,如果人们认为这是可行的方法,我仍然可以这样做。
新答案:
我现在是这样理解您的问题的。给定一个二元方阵 A,找到所有矩阵 B,使得 B 的每一行中的元素之和为 1,每列中的元素之和为 1,并且对于所有元素 B(r,c) == 1,原始矩阵 A(r,c) == 1 中的对应元素。
编辑 2:
这里的问题是您想找到所有的解决方案。其中有很多 很多。对于全 1 的 nxn 矩阵,您将拥有 n! 解决方案。对于每行都有m 1 的矩阵,您可能会有类似
mn-m * 米!
解决方案。因此,即使您有一个非确定性算法可以在 O(1) 时间内生成所有解决方案,简单地打印出来的时间复杂度仍然是指数级的。
正如 MrSmith42 在 cmets 中提到的,您可能需要进行回溯搜索,但您可以采取一些措施来减少搜索空间:
您可以进行的最简单检查是查找 A 中已经只有一个 1 的行/列。 (很明显,如果行/列中有 no 1,则没有有效的解决方案。)如果行 r 在列 c 中只有一个 1 ,将列 c 中的所有其他元素设置为 0。同样,如果列 c 在行 r 中只有一个 1,则设置中的所有其他元素
行 r 到 0。在你的例子中:
1 0 0 1 0 1 0 0 1 0 1 0 0 1 0
1 1 0 1 0 1 1 0 1 0 ==> 0 1 0 0 0
1 1 0 0 1 ==> 0 0 0 0 1 0 0 0 0 1
0 0 1 1 0 0 0 1 1 0 0 0 1 1 0
1 0 1 0 0 1 0 1 0 0 1 0 1 0 0
第 5 列只有一个 1,因此 B 中的第 3 行 必须在 B(3,5) 处有一个 1 才有效。这意味着我们可以修改我们的输入矩阵 A 并(稍微)减少搜索空间,而不会丢失任何有效的解决方案。从这里您现在在第 2 列中只有一个 1,并且可以将第 2 行中的其他值设置为 0。
接下来,您可以在搜索期间使用前向检查来防止搜索无法找到有效解决方案的子矩阵。假设给定以下矩阵:
1 0 0 1 0
0 1 1 0 1
1 1 0 0 1
0 0 1 1 0
1 0 1 0 0
没有只有一个 1 的行或列,所以我们开始赋值。假设我们已经按照回溯算法(在步骤 1 中)将第 4 列分配到第 1 行。我们将第 1 行和第 4 列中的其他条目设置为 x表明他们已经被分配:
Step 1 Step 2
1 0 0 1 0 ==> x x x 1 x x x x 1 x
0 1 1 0 1 0 1 1 x 1 ==> x x 1 x 1
1 1 0 0 1 1 1 0 x 1 1 1 x x 1
0 0 1 1 0 0 0 1 x 0 0 0 x x 0
1 0 1 0 0 1 0 1 x 0 1 0 x x 0
在第 2 步中,我们将第 3 列分配给第 2 行,并将行和列设置为已分配。
请注意,在第 4 行中,我们没有剩下任何 1,因此不可能通过此分配获得有效的解决方案。我们可以立即回溯,为第 2 行和第 1 行尝试不同的分配。
原始(错误)答案
每个可能的 nxn 矩阵,每行和每列只有一个 1,其余的 0 是单位矩阵的置换。也就是说,对于 n=5,您可以通过交换矩阵的行(或等效的列)来获取此类型的每个有效矩阵:
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
例如,如果将最后一行交换为行,您会得到:
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 0 1
0 0 0 1 0
要自动生成所有可能的有效矩阵,首先要为单位矩阵的每一行指定一个索引,例如从上到下 1-5:
1- 1 0 0 0 0
2- 0 1 0 0 0
3- 0 0 1 0 0
4- 0 0 0 1 0
5- 0 0 0 0 1
然后您只需生成所有 n! {1, 2, 3, 4, 5} 的可能排列。 {1, 2, 3, 5, 4} 的排序将为您提供上面的第二个矩阵。