编辑:
根据您的评论,我重新阅读了原始问题,并意识到我完全错过了问题的重点。我将在此处发布(希望)更相关的答案,但人们应该随时撤销任何赞成票。我讨论过发布一个新答案并删除这个答案,如果人们认为这是要走的路,我仍然可以这样做。
新答案:
这就是我现在如何理解你的问题。给定一个二元方阵 A,找到所有矩阵 B,使得 B 的每一行中的元素之和为 1,每列中的元素之和为 1,并且对于所有元素 B(r,c) == 1,来自原始矩阵 A(r,c) == 1 的对应元素。
编辑2:
这里的问题是你想找到所有的解决方案。而且还有很多。对于全 1 的 nxn 矩阵,您将有n!
解决方案。对于每行都有m
1 的矩阵,你可能会有类似的东西
米米*米!
解决方案。因此,即使您有一个非确定性算法可以在 O(1) 时间内生成所有解决方案,简单地将它们打印出来的时间复杂度仍然是指数级的。
正如 MrSmith42 在评论中提到的那样,您可能需要进行回溯搜索,但您可以采取一些措施来减少搜索空间:
您可以进行的最简单检查是查找 A 中已经只有一个 1 的行/列。(显然,如果行/列中没有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} 的排序将为您提供上面的第二个矩阵。