7

我有几个数字数组(数组的每个元素只能取0或1的值)像这样

v1:1;0; 0; 1个;1个;
v2:0;1个;0; 0; 1个;
v3:1;1个;0; 1个;0;
v4:1;0; 0; 1个;0;
v5:1;1个;0; 1个;1个;
v6:1;1个;0; 1个;1个;

我希望找到这样的子集,以便在对数组求和时,生成的数组具有单个元素,这些元素是 2 的倍数。例如,v1+v2+v3 给出的结果数组为 2、2、0、2、2。结果数组可以具有任何 2 的倍数的值。

另一个例子:

v1:1、1、1、0、1、0
v2:0、0、1、0、0、0
v3:1、0、0、0、0、0
v4:0、0、0、1、0、0
v5:1、1、0、0、1、0
v6:0、0、1、1、0、0
v7:1、0、1、1、0、0

在此示例中,v1+v2+v5 和 v3+v6+v7 是合适的答案。

我有一个蛮力解决方案,但我想检查是否有更有效的方法。这相当于子集和问题吗?

4

1 回答 1

1

您想找到所有解决方案还是一个?

这可以找到一种解决方案(我认为可以扩展它以找到所有解决方案)。

将每个数组表示为二进制数。

所以 v1 变成 10011,v2 变成 01001 等等。

让 * 表示按位 mod 2 加法。

例如

v1*v2*v3 = 00000

所以我们的目标是找到 mod 2 加法全为零的数组。令 u 和 v 为任意二进制数。然后 u*v = 0 当且仅当 u = v。

例如

(v1*v2)*v3 = 0
v1*v2 = 11010 = v3.

此外,如果 u*v = w 那么

u*v*v = w*v, so
u*0 = w*v,
u = w*v

所以我们可以从 0 开始进行反向搜索。假设最后一组数组包含 v。那么 v*T = 0,其中 T 是某个二进制数。我们有 T = 0*v。如果 T 是给定数组之一,那么我们就完成了。否则,我们从 T 开始继续搜索。

这在下面正式描述。

每个状态都是一个二进制数。

设 0 为初始状态。

给定的数组是状态空间的某个子集,比如 S。

我们的目标状态是 S 中的任何元素。

令 T 为总和为 0 的所需数组子集。

在每个状态,让可能的动作为 *,任何不在 T 中的状态。

在每个动作之后,将使用的数组放入 T 中。

如果 S = T 在任何非目标阶段,则没有解决方案。

现在我们可以在这个空间上运行一个 DFS 来寻找解决方案。

于 2012-05-12T11:04:56.060 回答