从6个随机数中计算出随机的三位数?

时间:2016-01-08 11:29:03

标签: php algorithm math

我有4年的PHP和C#经验,但数学不是我更好的一面。 我在这个项目中需要使用一些数学算法。

当页面加载我需要随机创建7个数字时,6个是我可以用来计算给定三位数的数字:

  • rand 1-9
  • rand 1-9
  • rand 1-9
  • rand 1-9
  • rand 10-100 // 5步
  • rand 10-100 // 5步

并且给定的数字是100-999,

我可以使用此操作: +, - ,/,*,(,)

这个的最佳算法是什么? 我可能需要尝试使用这6个数字的所有可能组合来计算给定数量或最接近的计算次数。

例如: 让我们说给出三位数的是 350,我需要从这个数字计算这个数字: 3,6,9,5,10,100 所以这个公式是: (100 * 3)+(5 * 10)= 350

如果无法计算确切的数字,则计算最接近的数字。

你不需要完全解决这个问题,你可以通过粘贴一些伪来解释这个问题,或者描述如何解决这个问题。

2 个答案:

答案 0 :(得分:3)

我没有可能对您有所帮助的实际经验,但是因为您要求提供一些见解,我将分享我对如何做到这一点的想法。

当我输入我的答案时,我意识到这实际上是knapsack problem,这意味着您可以使用解决背包问题的任何算法将其解决为最优。我建议使用dynamic programming让您的程序运行得更快。

您需要做的是构建您可以通过将两个数字与运算符组合生成的所有数字,以便在此之后您有一个列表,其中包含您开始使用的数字以及您生成的数字。

然后你用数字作为物品来解决背包问题,它们的值是它们的重量,而数字是你最多可以存储的重量。

唯一略有不同的是,您有一个额外的约束,表示您只能使用一次数字。因此,您需要在实现中添加如果添加数字组合,则必须删除存储使用相同数字构建的另一个组合的选项。

答案 1 :(得分:2)

您可以通过使用以下信息构建“抽象语法树”,二进制树来枚举所有解决方案:

  • 树叶是6个数字

  • 节点是操作,例如节点'+',左子的叶子为'7',右子的另一个节点为'x',左子为'140','8'为'8'对于右儿子将代表(7+(140 * 8))。此外,在每个节点上,您可以存储已使用的数字(树中使用的树叶)和总数。

假设您将所有构建的树存储在关联映射TreeSet中,但使用您使用的叶数进行索引。例如,树(7+(140 * 8))不会直接存储在TreeSet中,而是存储在TreeSets中[3](TreeSets [3]包含多个树,它也是一组)。

您在BestScore中存储最接近的分数,在BestSolution中存储BestScore的一个解决方案。

首先构建6个叶子(这使得6个不同的树只由一个叶子组成)。您可以在Bestscore中保存较近的数字,并在BestSolution中保存相应的叶子。

然后在每一步,你尝试用i叶子构建树,我从2到6,并将它们存储在TreeSets [i]中。

你从j到1到i-1,你把TreeSets [j]中的每棵树和TreeSets [ij]中的每棵树,你检查那两棵树不使用相同的叶子(你没有检查树的底部,因为你已经存储了节点中使用的叶子,如果是这样的话,你用TreeSets [j]中的树构建四个节点'+','x','/',' - '作为左儿子和来自TreeSets [ij]的树,并将它们全部存储在TreeSets [i]中。在构建节点时,从两个树中获取总数并应用操作,存储总数,然后检查它是否比BestScore更接近(如果是这样,则使用此新总计和新节点更新BestScore和BestSolution)。如果总数正是您要查找的值,则可以在此处停止。

如果你没有通过找到一个确切的解决方案来停止程序,那么就没有这样的解决方案,而最后一个解决方案就是BestSolution。

注意:您不必每次都构建一个完整的树,只需在其他树上构建带有两个指针的节点。

P.S。 :正如Glubus所说,你可以避免使用动态编程方法来枚举所有解决方案。在这种情况下,它将在每个步骤(i)中包括去除一些被认为是次优的解决方案。但是有了这个问题,我不确定是否可行(除了可能删除总共为0的节点)。

相关问题