使用最少的行和列切换将NxN二进制矩阵转换为零矩阵

Mik*_*ike 1 algorithm matrix

这是关于我发布的有关将一个NxN二进制矩阵转换为另一个NxN二进制矩阵的问题。我问的问题是一个代码挑战性问题。但是,如何通过行和列切换矩阵转换也提出了类似的问题。我经历了那个话题,对如何解决问题有了一些了解。我在这里重申这个问题。

“我想编写代码来解决以下问题。我计划使用C,C ++,Java或Python,具体取决于哪一种允许更方便的解决方案。给定两个NxN(1 <= N <= 2000)二进制矩阵(A问题是使用最小数量的允许操作将A转换为B,允许的操作是:
1.我们可以切换一行,
  这将切换该行中的所有值,即它将在该行
2
  中将1更改为0,将0更改为1。该列。
如果无法解决,我们将打印-1“

但是,我有以下疑问。

我了解到,找到将A转换为B所需的最小切换次数的第一步是计算A XORB。结果中的1是必须切换的位置,换句话说,必须将A XOR B转换为使用最小行和列切换次数的零矩阵。但是,我不清楚如何使用最少的行和列切换次数将A XOR B转换为零矩阵。有人可以说明一下吗?

谢谢。

P S*_*ved 5

相当容易的任务。

首先,我们应该理解,多次切换行或列是没有意义的。为了更好地理解,我们将状态表示为:每个像元中包含0或1,并且始终取模2的和的结果:

final[i,j] = initial[i,j] + row_switched[i] + column_switched[j]  (mod 2)
Run Code Online (Sandbox Code Playgroud)

其中row_switchedcolumn_switched是我们切换第i行和第j列的次数。现在很清楚,它们的值应该为0或1,以获取最少数量的开关。

但这实际上使...成为方程式的系统!我们知道初始状态(给定),我们知道最终状态(零),我们只需要针对r[i]和解决系统c[j]

不幸的是,由于模数以及因为它不包括r[i]c[j]所暗示的约束(为0或1),因此求解仍然很复杂。


让我们不用模数来重写这些条件:

row_switched[i] + column_switched[j] = 1  (if initial[i,j] = 1)
row_switched[i] - column_switched[j] = 0  (if initial[i,j] = 0)
Run Code Online (Sandbox Code Playgroud)

在为每个单元格编写了代码之后,我们获得了N ^ 2个方程的超定义系统。让我们用以下方法解决它。显然,如果我们知道的值row_switched[0],那么我们就会知道整个column_switched[]数组的值,因为它们是由参与其中的方程式明确推导的row_switched[0]。然后,很容易推导出每一行的值。

但是我们只有两个变量row_switched[0]:0和1。让我们尝试其中的每个变量(请参阅下面的内容),并为每个变量计算两个数组!然后,我们应检查所有方程式是否成立,并从满足整个系统且开关量较少的两个集合中选择一个。

如果两者都不满足,那么那是无法解决的。尝试解决这个问题,呵呵:

0 1
0 0
Run Code Online (Sandbox Code Playgroud)

这样就完成了解决方案。希望您能尝试+1。:)


关于为什么这是最少数量的开关的问题。实际上,任何有效数量的开关都应满足上面概述的方程组(0和1作为值的约束)。但是该系统最多只能有两个解决方案,我们可以在上述算法中找到它们。因此,以上算法必定找到最小的算法。


注意:在我看来,我们只能尝试其中之一。如果一个通过系统,则另一个也应该通过。一组是另一组的取反,因此我们只选择开关数量较少的一组即可。开关总和为2N。但这只是看起来,而且没有其他部分那么清楚。

  • 如果我的答案对您来说太长了,请对此评论投赞成票!:-)我需要反馈。:-) (2认同)