包含 - 排除的动态规划技术

时间:2015-07-13 18:16:53

标签: algorithm bit-manipulation

有N名士兵(编号从1到N)。每个士兵都拥有M种不同技能的一些技能(编号从1到M)。军队的技能组合是其组成士兵的技能组合。有多少不同的士兵子集满足具有特定技能要求 Problem



根据解释问题减少到找到这些数字的子集的数量,其OR正好等于所需的值,例如请求

设f(i)为数j的数量,使得j OR i = i。然后答案是Σi(-1)^ popcount(i xor req)(2 ^ f(i) -1)对于所有i,我或者req是req

该公式是如何产生的以及popcount如何描述它的增加或减少。

1 个答案:

答案 0 :(得分:0)

这是我的看法。解决问题的方法:而不是推理拥有某些技能的群体, 让我们理解那些没有某些技能的士兵 因为第二个属性从组传播到所有成员。

在我们开始之前,稍微简化一下:

在不失一般性的情况下,我们可以过滤掉至少有一项技能超出规定范围的士兵。因为子集的技能必须完全是所需的技能组合,所以永远不需要那些了解太多的聪明士兵。

从现在开始,我们假设所需的技能组合为{1, ... , R},并且士兵的技能介于1R之间。

我们需要A_i的定义(其中i属于{1,..,R}):

A_i:在小组技能组合中具有i 技能的士兵组

换句话说,A_i中的一个群组(inter表示交叉点)是一个至少有一名士兵拥有技能编号i的群组。

现在是i<j

A_i inter A_j =在小组技能组合中具有ij 技能的士兵小组

换句话说,A_i inter A_j中的一个群组是至少包含其中一个属性的群组

  • 一名技能编号为ij的士兵。
  • 两名士兵,一名技能i,一名技能j

并且

A_1 inter A_2 ... inter A_R

是在他们的小组技能组合中具有技能1,.., R的一组士兵。

问题所在的问题可以用A_i表示:

A_1 inter A_2 ... inter A_R的大小是多少?

等于

2^2^R - size( comp(A_1) union comp(A_2) ... union comp(A_R) )

其中comp(A)是补充集。

现在,我们可以应用包含 - 排除原则。

还有一个技巧可以使它成为可计算的:

如果I{1,..,R}的子集,则

中的组
intersection(comp(A_j) for all j in I)

I中没有技能(作为一个群体)的士兵群体。 请注意,这样一个群体中的士兵正是I中没有任何技能的士兵。 我们将g(I)定义为集合I中没有任何技能的士兵数量。有了这个,我们有

size( intersection(comp(A_j) for all j in I) ) = 2^g(I)

最后,我得到的结果是:

2^2^R - sum( (-1)^(size(I)+1) * 2^g(I) , for each I subset of {1,..,R} and I non-empty)

我希望这会有所帮助。如果有些事情仍然不清楚,请告诉我。