解
解决方案包括两个部分。首先我们发现最小集,然后证明它可以表示幂和集。解决方案针对编程实现进行了调整。
最小集算法
从和(多)集合中找到最大元素。P,潜在的最小(多重)集最初为空。amP
除非只有一组,表示中的所有可能的方式为一对,加起来总和的一米,š 我Ĵ = { (一个我,一个Ĵ)| a i + a j = a m }amamSij={(ai,aj)|ai+aj=am}
检查是否包括总和中的所有元素。
查找最大元素的所有小号我Ĵ具有以下属性(合意):每个s ^ 我Ĵ,一个小号或者是在小号我Ĵ,或者我们可以找到一个p从集合资金,使一个p + a s在S i j中。asSijSijasSijapap+asSij
如果它是,该情况下不包含一个小号,只是总和一个小号 + 一个p,删除一个p + 一个小号从小号我Ĵ(或只设置一个标志忽略它),然后插入一个p和一个š在小号我Ĵ代替。Sijasas+ap一种p+ 一个s小号我Ĵ一种p一种s小号我Ĵ
如果每个中都存在一个元素,则从所有S i j中将其删除一次(或仅设置一个标记以忽略该元素,不再触摸它)并将其添加到潜在最小集P的元素列表中。小号我Ĵ小号我ĴP
重复直到所有为空小号我Ĵ
如果某些保持为非空并且我们无法继续,请尝试使用所有S i j中的最大值。小号我Ĵ小号我Ĵ
重新创建递归步骤而无需删除,并继续使用幂集覆盖算法。(在此之前,您可以进行安全检查,以确保P包含所有不能表示为两个元素之和的元素,因此确保它们必须位于基础集中。例如,最小元素必须位于P中。)PPP
(10.请注意,作为算法目标的最小集解不能包含多个相同数目的重复。)
例:
{ 2 ,3 ,5 ,7 ,8 ,10 ,12 ,13 ,15 }
用所有可能的方式将15表示为总和中两个数字的总和。
(13 ,2 ),(12 ,3 ),(10 ,5 ),(8 ,7 )
尝试找到所有组中或可以表示为和的最大数。显然,我们可以从8开始搜索。
第一组中的13是13 = 8 + 5,所以13是可以的,但是第二组中的12是不好的,因为在和集中没有4使12 = 8 + 4。接下来,我们尝试7。但是无法立即覆盖13,没有6。
接下来,我们尝试5。13 = 5 + 8、12 = 5 + 7、10 = 5 + 5,最后一个是8 = 5 + 3或7 = 5 + 2,但不能同时使用两者。现在的组是:
((5 ,8 ),2 ),((5 ,7 ),3 ),((5 ,5 ),5 ),((5 ,3 ),7 )
5在所有组中重复,因此我们将其提取为。我们从每个组中仅提取5个。P= { 5 }
(8 ,2 ),(7 ,3 ),(5 ,5 ),(3 ,7 )
显然,没有点高于5,所以我们再次尝试5。8 = 5 + 3,7 = 5 + 2,所以一切都很好
((5 ,3 ),2 ),((5 ,2 ),3 ),(5 ,5 ),(3 ,(5 ,2 ))
从所有组中再次提取1至5,因为它在重复。(这是不常见的,但我们的情况是故意创建显示什么情况下,我们必须重复做。)P= { 5 ,5 }
(3 ,2 ),(2 ,3 ),(5 ),(3 ,2 )
现在我们尝试3并得到5 = 3 + 2。将其添加到组中。
(3 ,2 ),(2 ,3 ),(3 ,2 ),(3 ,2 )
现在提取3和2,因为它们重复无处不在,我们是细和组是空的。P= { 5 ,5 ,3 ,2 }
(),(),(),()
现在,我们需要不删除而重新创建递归步骤,这仅意味着执行上述操作而没有真正从删除元素,只需将它们放置在P中并标记不再更改即可。小号我ĴP
((5 ,8 ),2 ),((5 ,7 ),3 ),((5 ,5 ),5 ),((5 ,3 ),7
(13 ,2 ),(12 ,3 ),(10 ,5 ),(8 ,7 )
((5 ,(5 ,3 )),2 ),((5 ,(5 ,2 )),3 ),((5 ,(3 ,2 )),5 ),((5 ,3 ),(5 ,2 ))((5 ,8 ),2 ),((5 ,7 ),3 ),((5 ,5 ),5 ),((5 ,3 ),7 )
((5 ,(5 ,3 )),2 ),((5 ,(5 ,2 )),3 ),((5 ,(3 ,2 )),5 ),((5 ,3 ),(5 ,2 ))
动力装置覆盖
这部分的目的是检查找到的最小集合是否能够覆盖幂和集合。找到的解决方案有可能涵盖所有给定的总和,但它们不是幂集总和。(从技术上讲,您可以简单地从找到的最小集合中创建一个幂和集合,并检查每个和(如幂集合所指示的)是否在初始求和集合中。这就是所有与我们已经拥有的合并的东西,因此没有浪费。您可以在倒退递归时执行此部分。)
- 使用2的连续幂对最小值集中的所有元素进行编码。顺序并不重要。使用重复的新值对同一元素进行多次编码。从C = 1开始,每个下一个元素的C = 2C。
(2 = [ 1 ] ,3 = [ 2 ] ,5 = [ 4 ] ,5 = [ 8 ] )
- 替换还原的递归列表中的元素,
((5 ,(5 ,3 )),2 ),((5 ,(5 ,2 )),3 ),((5 ,(3 ,2 )),5 ),((5 ,3 ),(5 ,2 ))
编码:2与1、3与2、5与4,以及另外5与8。请注意,即使重复每个元素,其编码也不同。
((4 ,(8 ,2 )),1 ),((4 ,(8 ,1 )),2 ),((4 ,(2 ,1 )),8 ),((8 ,2 ),(4 ,1 ))
- 收集所有中间和,目前我们有(1,2,4,8)
((4 ,(10 )),1 ),((4 ,(9 )),2 ),((4 ,(3 )),8 ),((10 ),(5 ))
(1 ,2 ,3 ,4 ,5 ,8 ,9 ,10 )
((14 ),1 ),((13 ),2 ),((7 ),8 ),(15 )
(1 ,2 ,3 ,4 ,5 ,8 ,9 ,10 ,13 ,14 ,15 )
{ (15 ),(15 ),(15 ),(15 )}
2米− 1米m = 4
收集从缺失数字1个2米− 1
(6 ,7 ,11 ,12 )
- 用以下方式证明其不存在:以二进制形式表示每个数字
(6 = 01102)
(7 = 01112)
(11 = 10112)
(12 = 10102)
601102(2 = [ 1 ] ,3 = [ 2 ] ,5 = [ 4 ] ,5 = [ 8 ] ){ 2 ,3 ,5 ,7 ,8 ,10 ,12 ,13 ,15 },所以一切都很好。
701112(2 = [ 1 ] ,3 = [ 2 ] ,5 = [ 4 ] ,5 = [ 8 ] )
1112
如果有任何二进制表示形式对应于找不到的总和,请报告没有解决方案。
(2 ,3 ,5 ,5 )
讨论区
有必要提供一种算法,以检查总和是否覆盖了幂集完成,而幂集隐藏在二进制扩展中。例如,如果我们从初始示例中排除8和7,则第一部分仍将提供解决方案,只有第二部分将报告缺少的总和组合。
米Ñ 升ö 克(米)米日志2(米)米ñ日志(米)
米日志米米日志2(米)
米日志3(米)
该算法的某些部分假设我们可以在线性时间内找到一对和,因此需要进行排序。
启动错误
2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,152 ,3 ,4 ,6小号我Ĵ
5 ,4 ,3 ,3
2 ,2 ,3 ,4 ,42 ,3 ,4 ,6
一旦正确启动所有算法,此算法即可提供解决方案。
改进之处
步骤4.是可以这种方式升级的步骤:不是最大值,我们可以按满足给定条件的降序尝试每个元素。我们分别为每个分支创建一个分支。如果某个分支机构没有提供解决方案,请取消它。
2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,157 ,6 ,5 ,4因为它们都通过了第一个测试,所以采用了不同的方式。(没有理由使用2或3,因为我们知道它们必须在基础集合中。)并一直以这种方式继续进行,直到我们收集所有可以到达末尾的版本为止。这将创建一个全覆盖解决方案,它将发现多个基础集。
另一件事,因为我们知道如果情况最小,我们最多只能重复一次,因此可以将其合并到我们的算法中。
总体而言,第4步中每个组都必须重复一个数字或具有创建总和的能力的条件足够强大,足以使我们脱离直接指数水域,这将是简单地尝试每种组合并产生幂的算法。设置每个,直到我们找到一个匹配。