【问题标题】:Transforming a NxN binary matrix to a zero matrix using minimum row and column toggles使用最少的行和列切换将 NxN 二进制矩阵转换为零矩阵
【发布时间】:2009-09-28 21:19:35
【问题描述】:

这是关于我发布的关于将一个 NxN 二进制矩阵转换为另一个的问题。我问的问题是代码挑战问题。但是,How to do matrix conversions by row and columns toggles? 提出了类似的问题。我经历了那个线程,并且对如何解决问题有了一些想法。 我在这里重申问题。

“我想编写代码来解决以下问题。我打算使用 C、C++、Java 或 Python,取决于哪个更方便的解决方案。 给定两个 NxN (1 1. 我们可以切换一行,
 这将切换该行中的所有值,即它将在该行中将 1 更改为 0 并将 0 更改为 1
2. 我们可以切换一列,
这将切换该列中的所有值,即它将在该列中将 1 更改为 0 并将 0 更改为 1。
如果无法解决,我们打印 -1"

但是,我有以下疑问。

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

谢谢。

【问题讨论】:

    标签: algorithm matrix


    【解决方案1】:

    相当简单的任务。

    首先,我们应该明白多次切换一行或一列是没有意义的。为了更好地理解,我们这样表示状态:每个单元格中都有 0 或 1,并且总是取模 2 的总和的结果:

    final[i,j] = initial[i,j] + row_switched[i] + column_switched[j]  (mod 2)
    

    其中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)
    

    为每个单元格编写了这个,我们得到了一个 N^2 方程的过度定义系统。让我们通过以下方法解决它。很明显,如果我们知道row_switched[0] 的值,我们就会知道整个column_switched[] 数组的值,因为它们是由row_switched[0] 参与的方程明确推导出来的。然后很容易推导出每一行的值。

    但是对于row_switched[0],我们只有两个变体:0 和 1。让我们尝试它们中的每一个(见下面的注释),并为每一个计算两个数组!然后我们应该检查所有方程是否成立并选择满足整个系统开关较少的两组之一。

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

    0 1
    0 0
    

    这完成了解决方案。我希望你只是为了尝试而+1。 :)


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


    注意似乎在我看来,我们只能尝试其中一种。如果一个通过系统,另一个也应该通过。一组是对另一组的否定,所以我们只选择开关数较少的一组。开关总和为 2N。但这只是似乎,不如其他部分清楚。

    【讨论】:

    • 如果我的回答太长,您无法阅读,请投票支持此评论! :-) 我需要反馈。 :-)
    【解决方案2】:

    让我在How to do matrix conversions by row and columns toggles? 中再次解释我的答案的结尾。

    如果可能,我们已将问题简化为通过切换将矩阵转换为零矩阵。首先要注意,如果我们想要一个最小的答案,我们将永远不会多次切换行或列,因为切换行/列两次与不切换开始相同——身份的结果(P异或 1) 异或 1 = P。

    让我们看看第一行。第一行中的每个 1 都必须切换为 0。我们可以通过在第一行中用 1 切换每一列来做到这一点,我们可以切换第一行,交换 1 和 0,然后然后将每个新的 1 切换回 0。并且(假设没有切换对)这些是 only 两组操作,导致第一行减少为全 0。

    此时,查看其他行。如果任何一行有 0 或 1 的混合,你就完成了,问题是不可解决的;如果没有列切换,就无法使该行全为 0,这会破坏第一行中的 0。 OTOH,如果每隔一行全为 0 或全为 1,那么您只剩下行切换​​。

    最后一步是由于有 2N 种可能的切换,并且没有切换将成为两种解决方案的一部分。从上面的列切换中应该可以立即清楚地看到这一点;对于行切换,请注意,在一组列切换后全为 0 的行将在另一组列切换后全为 1。因此,在计算一组 K 个切换后,另一组的大小将为 2N - K 个切换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 2015-06-01
      • 2020-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      相关资源
      最近更新 更多