通过翻转1的矩阵的行和列来确定是否可以到达给定二进制矩阵的算法

时间:2018-02-27 12:11:24

标签: algorithm matrix time-complexity

我需要帮助找到一个尽可能有效的算法来检查是否可以通过仅用一个矩阵翻转矩阵的行和列来达到给定的二进制矩阵。 无论何时翻转行或col,0都变为1,所有1变为0

通过翻转矩阵的行和列来确定是否可以达到给定的二进制矩阵的算法

例如,可以通过翻转第二行然后翻转第二列来到达此矩阵:

New

但这个矩阵不能是你做的任何事情

+---+---+---+
| 1 | 0 | 1 |
+---+---+---+
| 0 | 1 | 0 |
+---+---+---+
| 1 | 0 | 1 |
+---+---+---+

2 个答案:

答案 0 :(得分:5)

可以按如下方式测试:

取目标矩阵的第一列。所有其他列应该与第一列相同,或者应该相反(翻转)。如果且仅当这种情况发生时,则可以通过具有全部1个值的初始矩阵的行/列的翻转来到达目标矩阵。

当然,您也可以使用行进行测试,但只需使用行或列执行测试即可。

要翻转哪个?

如果上述测试结果为阳性,您还可以查看可以执行哪些翻转以达到目标矩阵:

在目标矩阵的第一行中,标识值为0的单元格:这些是您需要在初始矩阵中翻转的列。

在目标矩阵的第一列中,识别值与目标矩阵左上角的值不同的单元格(因此这已经排除了第一个值):那些是你需要在初始矩阵中翻转的行。

翻转的顺序并不重要。显然,这只提供了一个解决方案。一般来说可以有不止一个。

实施

以下是一个简单的JavaScript代码段,可执行验证并提供可交换的列和行列表:



function getFlips(matrix) {
    // Verification
    for (let i = 1; i < matrix.length; i++) {
        let flip = matrix[i][0] ^ matrix[0][0]; // XOR operation
        for (let j = 0; j < matrix[0].length; j++) {
            if (matrix[i][j] ^ flip != matrix[0][j]) return false; // Not possible
        }
    }
    // If we get here, it is possible: determine which rows/columns to flip
    let flips = { rows: [], columns: [] };
    for (let j = 0; j < matrix[0].length; j++) {
        if (matrix[0][j] == 0) flips.columns.push(j+1);
    }
    for (let i = 1; i < matrix.length; i++) {
        if (matrix[i][0] != matrix[0][0]) flips.rows.push(i+1);
    }
    return flips;
}


// I/O management
inp.oninput = function () {
    // Convert input to matrix of numbers
    let matrix = inp.value.split('\n').map(row => Array.from(row, Number));
    // Perform algorithm
    let flips = getFlips(matrix);
    // Output the result in human readable format
    out.textContent = flips 
        ? 'Number(s) of the column(s) to flip: ' 
            + (flips.columns.length ? flips.columns : 'none') + '\n' +
          'Number(s) of the row(s) to flip: ' 
            + (flips.rows.length ? flips.rows : 'none')
        : 'Not possible';
};

inp.oninput();
&#13;
Enter the values of the matrix:<br>
<textarea id="inp" rows="4" cols="4">101
010
101</textarea><br>
Solution:
<pre id="out"></pre>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

考虑到我们有一个N乘N(方形)矩阵,我们可以使用动态规划在N个步骤中达到目标矩阵。

假设我们已经通过K子矩阵通过初始矩阵上的一些翻转来匹配左上角K.然后,通过翻转第K + 1行或/和第K + 1列,我们可以将子矩阵K + 1与K + 1匹配。在每个步骤中,我们可以选择以下四个选项之一:

  • 翻转第K + 1行,并翻转第K + 1列
  • 翻转K +第1行,而不是翻转第K + 1列
  • 不翻转第K + 1行,翻转K +第1列
  • 不翻转第K + 1行,不翻转K +第1列

对于每个选项,我们检查大小为K + 1的子矩阵是否与目标矩阵的相同区域匹配。如果它匹配,那么我们移动到下一步(K + 2),否则,我们停止搜索并得出两个原始矩阵不匹配的结论。我们继续这个过程,直到我们匹配大小为N的子矩阵。

因此,每次我们继续下一行和下一列,试图避免翻转先前的行/列,从而保持已经匹配的子矩阵不变。

这个过程是这样的:
1.我们通过翻转第一行/列来匹配左上角的1​​x1子矩阵 2.我们通过翻转第二行/列来匹配左上方的2x2子矩阵 3.我们通过翻转第3行/列来匹配左上3x3子矩阵 ...
N.我们通过翻转第N行/列来匹配左上NxN子矩阵