矩阵的每一行和每列中只有一个值

时间:2013-08-09 10:19:08

标签: algorithm matrix


我试图找出解决此问题的最佳方法: 有一个像这样的矩阵:

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,则我们可以检查每个生成的矩阵。如果是的话,这是一个解决方案。

生成所有这些矩阵需要哪些循环?

3 个答案:

答案 0 :(得分:3)

编辑:

根据您的评论,我重新阅读原始问题并意识到我完全错过了问题的重点。我会在这里发布(希望)更相关的答案,但是人们应该随意撤销任何赞成票。我辩论发布了一个新答案并删除了这个答案,如果人们认为这是可行的方法,我仍然可以这样做。

新答案:

以下是我现在理解你的问题的方法。给定方形二进制矩阵A,找到所有矩阵B,使得B的每一行中的元素之和为1,并且每列中的元素之和为1,并且对于所有元素B(r,c)== 1,来自原始矩阵A(r,c)的对应元素== 1。

编辑2:

此处的问题是您要查找所有解决方案。并且有很多很多。对于所有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 algorithmO(V.E)中运行

Hopcroft–Karp Algorithm for Maximum MatchingO(sqrt(V).E)中运行