给定一个由1和0组成的矩形,如何找到1的非重叠2x2正方形的最大数量?
示例:
0110
1111
1111
解决方案是2。
我知道它可以用Bitmask DP解决;但我真的无法抓住它 - 玩了几个小时之后。它是如何工作的以及如何正式化?
答案 0 :(得分:1)
这是一个动态编程解决方案。
状态为(row number, mask of occupied cells, shift position)
。它看起来像这样:
..#..
.##..
.#...
.#...
在这种情况下,行号是2(我使用零基索引),掩码取决于我们是否采用#
的单元格,移位位置是1.状态的数量是O(n * m * 2 ^ n)
。状态的值是拾取的2x2正方形的最大数量。基本情况是f(1, 0, 0) = 0
(它对应于第一行,到目前为止没有选择2x2方格)。
转换如下:
..#.. ..#..
.00.. -> ..1..
.0... .11..
.#... .#...
当且仅当正方形由原始矩阵中的正方形组成并且掩模中有零时(这意味着我们选择此正方形),可以使用此方法。 另一个是:
..#.. ..#..
.##.. -> ..#..
.#... .#0..
.#... .#...
这个始终适用。这意味着我们选择这个2x2平方。 当我们完成一行时,我们可以继续下一行:
..#.. ..#0.
..#.. -> ..#..
..#.. ..#..
.##.. ..#..
每个州最多有两个转换,因此总时间复杂度为O(n * m * 2 ^ n)
。答案是所有掩码中的最大值和最后一行的移位。
答案 1 :(得分:1)
我想指出的是,通过将顶点放在正方形的中心并在它们重叠时将它们连接起来而得到的图是 not 无爪的:
如果我们(在整个平面上)取一个2x2的正方形和四个对角重叠的2x2的正方形中的三个,则它们形成了诱导子图
• •
\ /
•
/
•
这是一个爪,意味着任何包含那些正方形的区域都对应于一个非爪图。
答案 2 :(得分:0)
如果你构建一个图形,其中每个节点代表一个2x2平方的1,并且如果它们重叠,则两个节点之间存在边缘,那么现在的问题是:在该图中找到最大独立集。
答案 3 :(得分:0)
编辑20:18,有一个由@ILoveCoding发布的反例
我的直觉说,这会奏效。我无法证明这一点,因为我还不够先进。但我无法想到任何反例。 我会尝试描述解决方案并发布代码,如果我的解决方案有误,请纠正我。
首先我们将输入加载到数组。 然后我们创建相同大小的第二个数组,并且对于每个可能的2x2平方放置,我们在第二个数组中标记1。对于OP发布的示例,这将如下所示。
0 1 0 0
1 1 1 0
0 0 0 0
然后,对于第二个数组中的每1个,我们计算邻居的数量(包括对角线)+ 1(因为如果它没有任何邻居,我们仍然必须将它看作1)。我们将这些新数字设置为数组。现在看起来应该是这样的。
0 4 0 0
3 4 3 0
0 0 0 0
然后,对于数组中的每个非零值,我们检查它是否有任何具有更大或相等值的邻居。如果它继续前进,因为它不能在解决方案中。 如果我们没有找到任何这样的价值,那么它将在解决方案中。我们必须将原始值的每个邻居重置为零(因为它不能在解决方案中,它会与解决方案重叠。
所以找到的第一个这样的数字应该是左边的2。处理完后,数组应该如下所示。
0 0 0 0
3 0 3 0
0 0 0 0
当我们检查其他3个情况是一样的时候。
我们最终在数组中得到非零值,表示2x2正方形的左上角位置。
如果你需要它们的数字,只需遍历数组并计算非零元素。
另一个例子
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 6 0 6 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 0 0 0 0 -> 0 0 0 0 -> 0 0 0 0
我写的代码可以在这里找到 http://ideone.com/Wq1xRo