比迭代所有组合更简单的解决方案

时间:2014-09-02 16:43:30

标签: c++ vba loops combinations

设计具有以下内容的程序:

长度未知的初始数组,只有2和6的

初始数组 {2,2,2,2,2,2,6,6,6,6,6,6}

目标是使用初始数组找到最小数量的数组,其总和小于或等于16 错误的答案是

4个数组:

  • 数组1 {2,2,2,2,2,2}
  • 数组2 {6,6}
  • 数组3 {6,6}
  • 阵列4 {6,6}

正确的答案是

3个数组:

  • 数组1 {6,6,2,2}
  • 数组2 {6,6,2,2}
  • 数组3 {6,6,2,2}

我的解决方案是逐步完成每个可能的解决方案,跟踪所需的阵列。如果先前的解决方案具有相同数量的阵列或小于当前的阵列,则抛出当前的阵列。由于可能比较(6,6)和(6,6)......

的差异,这似乎有点密集

我正在阅读如何迭代不同的组合。大多数与扑克有关的文章我确信我可以与二十一点画出一些相似之处(21)。

由于以下原因,我希望“快捷方式”可能起作用:

  1. 可能的条目只有2& 6的
  2. 总结不到16 ......不能过去
  3. 最后的评论:我会喜欢有关如何继续的任何信息......逻辑......阅读本文..等等。

    谢谢, 乔希

2 个答案:

答案 0 :(得分:3)

在做出任何假设之前,请先解释一下您的问题。

首先,没有多少方法可以安排6和2来得到16的总和。事实上,只有3:

2*6+2*2 = 6+6+2+2
1*6+5*2 = 6+2+2+2+2+2
0*6+8*2 = 2+2+2+2+2+2+2+2

其次,你可以总结2来获得6:2+2+2 = 6

第三个(来自第一个),数组中不能超过2个。

现在,我认为解决方案非常简单。 但是,我没有证据,所以不要理所当然。

从第二和第三,我认为你最好先摆脱6。所以你可以按照这样的数组成对打包它们:{6, 6, 2, 2}。如果你没有足够的2来填写,只是不要填写。

如果您的奇数为6,那么最后一个将出现在如下数组中:{6, 2, 2, 2, 2, 2}

如果还有剩下的话,你只需要填写2的数组:{2, 2, 2, 2, 2, 2, 2, 2}

尽管事实上我没有证据(可能是因为我很懒惰),但我觉得这是一个解决方案,并且它不涉及任何类型的复杂组合术。

请注意针对您描述的解决方案进行测试?

修改

以下是对我的评论的更正,以及证明我的解决方案确实是一个很好的解决方案。

让我们在初始数组中调用n2n6 2和6的数量,并在初始数组中调用sum元素的总和(6 + 6 + ... + 2 + 2 + ...)。

所需的数组数量不是ceil((3*n6 + n2)/8) = ceil(sum/16)。如果你有9个6和2没有它不起作用:它给4而不是5。这是因为你不能用6完全填充数组(总和将是12,而不是16),但你可以用2的。然后正确的公式为max(ceil(sum/16), ceil(n6/2))

现在为整个解决方案。让我们保留符号n2n6sum

将您的阵列视为16米长的盒子(用您想要的任何线性单位替换m),2作为2米长的块,6作为6米长的块。为了在尽可能少的方框内排列所有块,您想要的是在每个阵列中放置您可以使用的块的最大长度(而不是数量)。这很明显:你需要在16米的最小方框中安装sum米。

因此,解决问题的方法是将框填满最多。使用2,很容易:你可以在一个盒子里放八个2米长的块。使用6,你只能将两个6米长的积木放在一个盒子里,而不用填满它。

如果你只有6个,只需在每个框中加上最大值(每个框中有两个),然后就可以获得数组了。在这种情况下,数组的数量是ceil(n6/2)

如果您只有2个,请执行相同操作(每个框中有8个)。在这种情况下,数组的数量为ceil(n2/8)

如果你有两个,你可以打包两个6和两个2来填充一个盒子,所以就这样做!我们已经知道它是适合每个阵列中最大块长度的最佳解决方案,你不能做得比16m = 2 * 6m + 2 * 2m更好。
当你用完一种区块时,这就是做什么 如果你用完了6个,那么你可以用2个填满其余的盒子:每个下一个盒子最多可以达到16米,直到你用完2个,在这种情况下你有floor(sum/16)个盒子满满的,也许是一个部分填补。因此,在这种情况下,数组的数量为ceil(sum/16) 如果你用完2个,那么丢弃你刚放入盒子里的每2米长的块。你剩下的是一对6米长的盒子,好像你没有任何2个开始。然后你有了解决方案:在每个盒子里放两个6米长的块。你可以把剩下的2放回去,因为你知道它们不会溢出。在这种情况下,数组的数量也是ceil(n6/2)

现在,如何知道每种情况下所需的数组数量?好吧,我们有3个可能的公式,需要采取最大值:ceil(n6/2)ceil(n2/8)ceil(sum/16)。但我们知道ceil(n2/8)不能大于ceil(sum/16),因为sum = 6*n6 + 2*n2sum/16 = 3/8 *n6 + n2/83/8 *n6不是负数。

但是,ceil(n6/2)可能会大于ceil(sum/16) 例如:n6 = 9, n2 = 0。然后ceil(n6/2) = 5,但ceil(sum/16) = 4

最后,正确的公式是max(ceil(sum/16), ceil(n6/2))

答案 1 :(得分:0)

由于你的目标只涉及2s和6s,你可以使用贪心算法(因为6至少是2的2)。这意味着您只需从源数仍然低于16的最大数字中取出并将其添加到当前数组中。如果没有新数字,则启动一个新数组。

从这种方法来看,很明显你可以根据源数组中2s和6s的数量将其简化为公式:换句话说,你做一个2s和6s的线性计数,然后使用常量时间公式确定数组的数量。