2016-12-14 35 views
0

故事

我想让我的祖母着名的N豆汤。该配方需要准确的N个豆子。找到物品的最佳组合,以最低的成本。也许背包变种?

杂货店只出售预包装袋中的豆类。每个袋子都包含一定数量的豆子,价格不同。

1000 for $300 ($.3 per bean) 750 for $225 ($.3 per bean) 600 for $180 ($.3 per bean)

300 for $150 ($.5 per bean) 250 for $125 ($.5 per bean) 100 for $50 ($.5 per bean)

10 for $10 ($1 per bean) 5 for $5 ($1 per bean) 1 for $1 ($1 per bean)

联邦食品法规定,豆大的袋子将永远不会有AA更昂贵的每个bean的成本比一个小袋子,但它可以等于。总之,一袋中的豆越多,价值越高。

当我去商店时,我需要确保我购买至少N豆的配方。我也想尽可能少花钱。我不在乎是否购买比我需要的更多的豆,我只是想确保我得到最好的交易来做到这一点。 我想购买能够以最低价格购买至少N颗豆子的包装袋。

我该怎么做?

我想写一个算法,它会很快计算出来。不幸的是我需要在我正在写的游戏中经常调用它,在这里你可以拖动一个值滑块来改变配方所需的Beans数量。

这个问题与背包问题或制造变更问题非常接近,但与众不同,因为我不在乎所采取的物品数量,而是关心总体成本。我认为动态规划是一条可行的路线,但我并没有真正理解它,因此开始将问题分解为更小的块。

以下是我目前的想法:我想写一个函数来创建一组可能的Bean Bag购买。我想先评估高数量(最高价值)的包包。我必须自上而下,因为根据联邦法律,自下而上会创造低价值的结果,我知道这样会更加昂贵。

我想创建一个函数,在每次购物时分支,并计算如果我做过或者没有再购买一个特定行李,然后继续计算会发生什么。它从最昂贵的包开始,并逐渐降低

我认为我应该将这些可能的组合存储为2维数组,其中“列”是您购买的包的数量,并且每行代表完成袋子组合以达到目标豆的数量。在计算可能的有效交易之后,我可以啃过二维阵列,找到总成本最低的那一个,如果其中有几个相同,我选择购买总数最少的袋子。

我觉得我的代码会做

例如,比方说我的食谱要求1602种豆。我首先购买2×1000个计数袋,总计600美元。这是一个有效的购买,但也许不是最好的交易。购买第三千个计数袋将是无效的,所以我改为分支,只购买1x1000计数袋和1x750计数,总计525个。更好的交易!然后我再次分支,并购买1x1000 + 2x600 = 660美元,这是更糟糕的。再次分支:1x1000 + 1x600 + 1x300 = 630美元。依此类推,直到我以482美元达到1x1000 + 1x600 + 2x1。这是最好的交易,但我还不知道,我必须咀嚼下一个分支点。

问题

我的大问题是:我想我可以写一个递归循环经历和评价每一个可能的收购。但是,我怎么知道我什么时候可以尽早摆脱这个循环?在什么时候我可以肯定地说:“好吧,最后一个分支证明我没有必要进行进一步的计算,我已经找到了最好的交易,我们现在停下来,节省时间”

这样的问题有一个名字?它是什么样的背包问题的变种?

谢谢!

回答

1

是的,这属于背包区域的松散解释。

详细

首先,使用动态规划:从阵列中的每个调用保存的结果。 永不第二次计算该值。

您的基本分界点是当您尝试购买与解决方案中已有的其他人相结合的袋子时,等于大袋子的数量。保留那里的解决方案;一个更高的分支会为你找到更大的麻袋。

请注意,这适用于合并解决方案:每次返回后检查。例如,如果你只有7个豆子,你的呼叫将返回(5,1,1)。如果你在更高的解决方案中已经有了一个5豆袋,放弃那个分支 - 一个更高的分支将(或已经)找到了10豆解决方案。

更高的处理

你可以建立快捷方式的列表,如果你在事先确定的基本组合:3座100豆袋制作300等,这可以让你主动限制数量任何解决方案路径中的100个豆袋。然而,在一般混乱的环境中,这对大多数物质不会分裂另一个物体并没有多大帮助。我不会为混合组合而烦恼,因为在每次返回时测试多个匹配会使代码复杂化,但返回的代价很小。

测试

确保您尝试某些情况下,最大的包和一些小的比的中袋组合更加昂贵。

尝试一些奇怪的情况:2的幂次,斐波那契数量,素数等。