我在编程比赛中遇到了这个问题:
我们给了一个由n个元素组成的数组。在每次迭代中,您可以选择任意两个元素 a i 和 a j 并替换 a < sub> i 和 a i 和a j 。 &是按位AND运算符。 找到使所有数组元素为零所需的最少AND操作。
假设给定输入有解决方案。该问题的最佳解决方案是什么?
编辑: 我已为该问题添加了DP解决方案,该解决方案需要1秒钟以上的时间才能运行。有什么建议可以加快速度吗?
0
D:以2为底的最大位数(0
目标:2 ^ D-1
T [i] [X] =>来自{n_0,n_1,...,n_i}的使X为零的最小元素数
T [i] [0] = 0
T [0] [X> 0] = INF
T [i] [X] = min(1 + T [i-1] [X&n_i],T [i-1] [X])
T [n] [GOAL]->最小AND操作数
答案 0 :(得分:9)
在我看来,这就像set cover problem。我们需要找到在每个位置都覆盖零的最小子集。找到该子集后,可以使用生成的“绝对”零将其他元素转换为零。在下面的示例中,子集中的三个元素中的任何一个都可以用作第一个零。
1001
0101<
0011<
1110<
0111
答案 1 :(得分:5)
如果问题对于给定的输入有解决方案,则可以执行以下操作:
在[0,n-1]之间选择索引i(假设数组索引基于零)。
对于介于0和n之间的每个非i的j,执行 i <-a i 和a j 。此时,可以确保a_i等于0,否则该问题将无法解决,因为您对数组中的所有项目按位执行了操作。
对于介于0和n之间的每个非i的j,执行 j <-a i 和a j 。这将对数组中的所有项目执行0,并将它们也设为0。
您在第一个循环中执行和运算n-1次,在第二个循环中执行n-1次,因此总共执行2n-2次和运算。
编辑:
这是假设您无法查看数组中的值。
答案 2 :(得分:3)
我的猜测是,通过使DP表稀疏可以获得所需的加速。我们可以认为结果算法是在节点为2^D-1
且边沿从0
到{的图上进行从0..2^D-1
到x
的广度优先搜索。 {1}},其中x&y
是一个数组元素。实际上,由于按位AND的可交换性/缔合性,我们可以通过要求y
清除x&y
中设置的最低位来加强边集。在下面的Python代码中,这可以通过使用映射x
在某种程度上有效地实现,但是在C语言中,我将使用一个数组(并使用位图或数组适当地替换这些集合)。
zero_index