使所有数组元素为零的最少AND操作数

时间:2019-02-25 12:58:39

标签: algorithm data-structures dynamic-programming greedy

我在编程比赛中遇到了这个问题:

  

我们给了一个由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操作数

3 个答案:

答案 0 :(得分:9)

在我看来,这就像set cover problem。我们需要找到在每个位置都覆盖零的最小子集。找到该子集后,可以使用生成的“绝对”零将其他元素转换为零。在下面的示例中,子集中的三个元素中的任何一个都可以用作第一个零。

1001
0101<
0011<
1110<
0111

答案 1 :(得分:5)

如果问题对于给定的输入有解决方案,则可以执行以下操作:

  1. 在[0,n-1]之间选择索引i(假设数组索引基于零)。

  2. 对于介于0和n之间的每个非i的j,执行 i <-a i 和a j 。此时,可以确保a_i等于0,否则该问题将无法解决,因为您对数组中的所有项目按位执行了操作。

  3. 对于介于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-1x的广度优先搜索。 {1}},其中x&y是一个数组元素。实际上,由于按位AND的可交换性/缔合性,我们可以通过要求y清除x&y中设置的最低位来加强边集。在下面的Python代码中,这可以通过使用映射x在某种程度上有效地实现,但是在C语言中,我将使用一个数组(并使用位图或数组适当地替换这些集合)。

zero_index