我试图找出解决此问题的最佳方法:
有一个像这样的矩阵:
1 0 0 1 0
1 1 0 1 0
1 1 0 0 1
0 0 1 1 0
1 0 1 0 0
我们想找出每个可能的矩阵,其中每行和每列只有一个1,例如这个矩阵是一个可能的解决方案:
1 0 0 0 0
0 1 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 1 0 0
我认为您可以找到一个解决方案,通过每个可能的组合循环,并检查每行和每列中是否只有一个1?有没有任何已知的算法? 有可能实际计算解决方案而不是尝试所有可能性吗?
非常感谢!
编辑: 一种可能的解决方案(但价格昂贵)可能是生成每个理论上可能的矩阵,例如(使用3x3矩阵,因为它更短): 1。
1 0 0
0 1 0
0 0 1
2
1 0 0
0 0 1
0 1 0
3
1 0 0
0 0 1
0 1 0
4。
0 1 0
1 0 0
0 0 1
5
0 1 0
0 0 1
1 0 0
等
然后,如果原始矩阵在给定位置具有1,则我们可以检查每个生成的矩阵。如果是的话,这是一个解决方案。
生成所有这些矩阵需要哪些循环?
答案 0 :(得分:3)
根据您的评论,我重新阅读原始问题并意识到我完全错过了问题的重点。我会在这里发布(希望)更相关的答案,但是人们应该随意撤销任何赞成票。我辩论发布了一个新答案并删除了这个答案,如果人们认为这是可行的方法,我仍然可以这样做。
以下是我现在理解你的问题的方法。给定方形二进制矩阵A,找到所有矩阵B,使得B的每一行中的元素之和为1,并且每列中的元素之和为1,并且对于所有元素B(r,c)== 1,来自原始矩阵A(r,c)的对应元素== 1。
此处的问题是您要查找所有解决方案。并且有很多很多。对于所有1的nxn矩阵,您将获得n!
个解决方案。对于每行有m
1的矩阵,您可能会有类似
m n-m * m!
的解决方案。因此,即使您有一个非确定性算法在O(1)时间内生成所有解决方案,简单打印出来的时间复杂度仍然是指数级的。
正如MrSmith42在评论中所提到的,你可能需要进行回溯搜索,但是你可以采取一些措施来缩小搜索范围:
您可以进行的最简单的检查是在A中查找已经只有一个1的行/列。 (显然,如果其中有没有 1的行/列,则没有有效的解决方案。)如果行 r 在列 c中只有一个1 ,将列 c 中的所有其他元素设置为0.同样,如果列 c 只有一行 r ,请设置所有其他元素 行 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}的排序将为您提供上面的第二个矩阵。
答案 1 :(得分:1)
我写了这个简单的代码(使用你的矩阵):
A=[1 0 0 1 0;
1 1 0 1 0;
1 1 0 0 1;
0 0 1 1 0;
1 0 1 0 0]
[row,col]=size(A);
B=zeros(row,col);
for i=1:col
[one_row,~]=find(A(:,i)==1); %one_row says in wich row of the "i" column there are ones
where_row=min(one_row); %we're interested only in one of those "ones".I'm taking the first found
B(where_row,i)=1; %inserting in the output matrix
end
B %for visualization purposes
我希望它适合你。
答案 2 :(得分:1)
这是两方面的匹配问题。
考虑一个二部图,其中在一组(R)中有r个顶点,在另一组(C)中具有c个顶点,其中r和c分别是行数和列数。
如果元素i
在给定矩阵中为1,则顶点j
(在R中)和顶点[i,j]
(在C中)之间的边存在。
如果要查找最大数目为1(最大二分匹配)的矩阵,可以使用
Maximum Bipartite Matching using Ford-Fulkerson algorithm在O(V.E)
中运行
或
Hopcroft–Karp Algorithm for Maximum Matching在O(sqrt(V).E)
中运行