这不完全是关于代码的问题,但是我需要有关算法逻辑的一些帮助。
给出一个NxN矩阵,该矩阵在每一行和每一列上至少有一个零值,您将如何选择N个零,以便在每一行和每一列上都有一个正好值?例如:
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5
0 8 0 1 3
8 6 0 1 3
很显然,您首先必须选择在每一行或每一列上都是奇数的零。我不确定在几行和几列上是否有相等数量的零。我该如何选择最佳值,以便不遗漏任何行或列?
答案 0 :(得分:2)
这是找到maximum cardinality matching in a bipartite graph的问题:行代表一组顶点u_1,u_2,...,u_N,列代表另一组v_1,v_2,...,v_N,并在那里每当矩阵位置(i,j)为0时,就是边缘u_i-v_j。
可以在O(N ^ 3)时间使用最大流量算法(例如Ford-Fulkerson)解决问题,或者在O(N ^ 2.5)时间使用更专业的Hopcroft-Karp算法解决。实际上,这些算法解决了一个稍微更普遍的问题:它将找到最大可能的一组唯一的(行,列)对,这样每个对在矩阵中都为0。 (在您的情况下,您碰巧知道有N个这样的对的解决方案:这显然是最好的。)
答案 1 :(得分:0)
选择具有最少零个数的行。
对于该行中的每个零,选择其列中具有最少零个的那个。
以某种方式标记该行和列(也许在存储选定零的索引后从它们中删除所有的zeor?这取决于您)。
在下一次迭代中将跳过标记的行和列。
重复直到遍历所有未标记的行和列,或者直到无法构建进一步的解决方案为止。
因此对于示例问题,这是可视化解决方案的方式(<
和^
表示标记的行和列):
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5
0 8 0 1 3
8 6 0 1 3 //具有最少零且最后一个被访问的行
迭代1:
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5
0 8 0 1 3
8 6 0 1 3 << / p>
_ _ ^ _ _
迭代2:
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5 << / p>
0 8 0 1 3
8 6 0 1 3 << / p>
_ ^ ^ _ _
迭代3:
0 4 6 0 2
0 8 9 5 0 << / p>
4 0 9 8 5 << / p>
0 8 0 1 3
8 6 0 1 3 << / p>
_ ^ ^ _ ^
迭代4:
0 4 6 0 2 << / p>
0 8 9 5 0 << / p>
4 0 9 8 5 << / p>
0 8 0 1 3
8 6 0 1 3 << / p>
_ ^ ^ ^ ^
迭代5:
0 4 6 0 2 << / p>
0 8 9 5 0 << / p>
4 0 9 8 5 << / p>
0 8 0 1 3 << / p>
8 6 0 1 3 << / p>
^ ^ ^ ^ ^