【问题标题】:exactly one value in each row and column of a matrix在矩阵的每一行和每一列中恰好有一个值
【发布时间】:2013-08-11 06:08:06
【问题描述】:


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

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。如果是,这是一个解决方案。

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

【问题讨论】:

  • 使用回溯减少搜索空间。与经典回溯唯一不同:找到第一个解得到所有解时不要退出。
  • 如果你必须生成每一个个令人满意的矩阵,那么就无法摆脱蛮力的复杂性:考虑由全1组成的输入矩阵。

标签: algorithm matrix


【解决方案1】:

编辑:

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

新答案:

我现在是这样理解您的问题的。给定一个二元方阵 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} 的排序将为您提供上面的第二个矩阵。

【讨论】:

  • 好的,我将研究一种用于某种回溯/蛮力方法的算法,但我想如果矩阵的大小更大并且 1 和 0 的组合不是最佳的,它可以运行得很好一会儿。我想我必须实现最大循环数。
  • 真的不能通过某种公式来解决吗?这是一个类似于旅行商问题的问题吗?
【解决方案2】:

我已经写了这个简单的代码(使用你的矩阵):

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

我希望它对你有用。

【讨论】:

  • 谢谢!如果我理解正确,这只是一个循环,如果第一个循环不是解决方案,我们就找不到解决方案。如果我们没有解决方案并检查所有可能的解决方案,外部循环会如何继续?
【解决方案3】:

这是一个二分匹配问题。

考虑一个二部图,其中一个集合 (R) 中有 r 个顶点,另一个集合 (C) 中有 c 个顶点,其中 r 和 c 分别是行数和列数。 顶点i(在集合R中)和顶点j(在集合C中)之间的边存在当且仅当元素[i,j]在给定矩阵中为1。

如果您想找到最大数量为 1 的矩阵(最大二分匹配),您可以使用

Maximum Bipartite Matching using Ford-Fulkerson algorithmO(V.E) 中运行

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

【讨论】:

    猜你喜欢
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    • 2019-11-15
    • 2019-04-13
    相关资源
    最近更新 更多