找到满足特定条件的子集
Posted
技术标签:
【中文标题】找到满足特定条件的子集【英文标题】:Finding a subset which satisfies a certain condition 【发布时间】:2012-01-22 08:32:32 【问题描述】:我有几个这样的数字数组(数组的每个元素只能取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 是合适的答案。
我有一个蛮力解决方案,但我想检查是否有更有效的方法。这相当于子集和问题吗?
【问题讨论】:
你能详细说明一下:1.) 集合有多长 2.) 你需要结果和数组吗? 每个数组的元素个数和数组的个数在程序开始时是未知的。我实际上并不需要 sum 数组。只是数组的数量。所以如果结果是 v1+v2+v5,我需要 1、2、5。 @Banthar wow.. 高斯消除似乎是正确的做法。我只需要找到 Vx=0 的所有可能解决方案,其中 V 是我所有数组的矩阵。我想 x 会给我相应的行号。 关于 gauss-Jordan:记住 x 在每个维度上都被限制为 0/1;并且您在每个维度中再次寻找“=0 mod 2”,而不是“=0”(这与将其视为适用于 Vx 的任何规范的“=0 mod2”不同,例如。 @Neo,高斯消除对你有用吗?如果是这样,您可以将其发布为答案并接受吗? 【参考方案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 来寻找解决方案。
【讨论】:
以上是关于找到满足特定条件的子集的主要内容,如果未能解决你的问题,请参考以下文章